def test_nested_query(self): query_string = 'assignments.assignee_id:someuse' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'nested': {'path': 'assignments_nested', 'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'someuse'}}]}}}}]}}
def test_very_complicated_query(self): query_string = '((assignments.assignee_id:someuser OR assignments.is_completed:false) ' \ 'OR (value:true AND another:false AND (some:true AND NOT field:true)) ' \ 'AND NOT (complicated:true OR complicated:false)) ' \ 'OR owner_id:someuser AND NOT completed:false' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'bool': { 'must_not': [{'term': {'completed': 'false'}}], 'should': [{'bool': { 'must_not': [{'bool': { 'should': [{'term': {'complicated': 'true'}}, {'term': {'complicated': 'false'}}], 'minimum_should_match': 1}}], 'should': [{'bool': { 'should': [{'nested': {'path': 'assignments_nested', 'query': {'bool': { 'should': [{'term': {'assignments_nested.assignee_id': 'someuser'}}, {'term': {'assignments_nested.is_completed': 'false'}}], 'minimum_should_match': 1}}}}], 'minimum_should_match': 1}}, {'bool': {'must': [{'term': {'value': 'true'}}, {'term': {'another': 'false'}}, {'bool': { 'must': [{'term': {'some': 'true'}}], 'must_not': [{'term': {'field': 'true'}}]}}]}}], 'minimum_should_match': 1}}, {'term': {'owner_id': 'someuser'}}], 'minimum_should_match': 1}}]}}
def test_simple_query_with_parentheses(self): query_string = '(assignments.assignee_id:"qweqweqwe")' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'nested': {'path': 'assignments_nested', 'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'qweqweqwe'}}]}}}}]}}
def test_nested_query_and(self): query_string = 'assignments.assignee_id:someuse AND assignments.is_completed:true' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': {'must': [{'bool': {'must': [{'nested': {'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'someuse'}}, {'term': {'assignments_nested.is_completed': 'true'}}]}}, 'path': 'assignments_nested'}}]}}]}}
def test_nested_query_with_quotes(self): query_string = 'assignments.assignee_id:"[email protected]."' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'nested': {'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': '[email protected].'}}]}}, 'path': 'assignments_nested'}}]}}
def test_do_not_apply_needless_parentheses(self): query_string = '((((assignments.assignee_id:someuse)) AND ((assignments.is_completed:true))))' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': {'must': [{'bool': {'must': [{'nested': {'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'someuse'}}, {'term': {'assignments_nested.is_completed': 'true'}}]}}, 'path': 'assignments_nested'}}]}}]}}
def test_nested_query_and_with_quotes(self): query_string = 'assignments.assignee_id:"someuser.some.last.name" ' \ 'AND assignments.assignor_id:"changed.user.name"' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': {'must': [{'bool': {'must': [{'nested': {'path': 'assignments_nested', 'query': { 'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'someuser.some.last.name'}}, {'term': {'assignments_nested.assignor_id': 'changed.user.name'}}]}}}}]}}]}}
def test_parse_statement_inside_param_value(self): query_string = '(assignments.assignee_id:"qweqweqwe")' params = {'es_q': query_string, 'project_id': '(2 OR 3)'} result = compile_es_query(params) assert result == {'bool': { 'must': [{'bool': { 'must': [{'nested': {'path': 'assignments_nested', 'query': {'bool': {'must': [{'term': {'assignments_nested.assignee_id': 'qweqweqwe'}}]}}}}, {'bool': {'should': [{'term': {'project_id': '2'}}, {'term': {'project_id': '3'}}], 'minimum_should_match': 1}}]}}]}}
def test_range_query_with_brackets(self): query_string ='((schedules.end_date:[2016-10-11T03:00:00 TO 2016-10-18T02:59:59]))' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'nested': {'query': {'bool': { 'must': [{ 'range': {'schedules_nested.end_date': {'gte': '2016-10-11T03:00:00', 'lte': '2016-10-18T02:59:59'}}}]}}, 'path': 'schedules_nested'}}]}}
def test_range_query_nested(self): query_string = 'schedules.end_date:[2016-10-11T03:00:00 TO 2016-10-18T02:59:59] AND schedules.obj_status:active' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'bool': { 'must': [{'nested': {'query': {'bool': { 'must': [{'range': {'schedules_nested.end_date': { 'lte': '2016-10-18T02:59:59', 'gte': '2016-10-11T03:00:00'}}}, {'term': {'schedules_nested.obj_status': 'active'}}]}}, 'path': 'schedules_nested'}}]}}]}}
def test_nested_query_inside_query(self): query_string = '(assignments.assignee_id:someuser OR assignments.is_completed:false AND assignments.assignor_id:another) OR owner_id:someuser' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'bool': { 'should': [{'bool': { 'should': [{'nested': {'path': 'assignments_nested', 'query': {'bool': { 'should': [{'term': {'assignments_nested.assignee_id': 'someuser'}}, {'term': {'assignments_nested.is_completed': 'false'}}], 'minimum_should_match': 1}}}}], 'must': [{'nested': {'path': 'assignments_nested', 'query': {'bool': { 'must': [{'term': {'assignments_nested.assignor_id': 'another'}}]}}}}], 'minimum_should_match': 1}}, {'term': {'owner_id': 'someuser'}}], 'minimum_should_match': 1}}]}}
def test_do_not_apply_needless_parentheses_with_statements(self): query_string = '((((assignments.assignee_id:someuse)) AND ((assignments.is_completed:true))) OR assignments.is_completed:brayan)' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': { 'must': [{'bool': { 'must': [{'nested': {'query': {'bool': { 'must': [{'term': {'assignments_nested.assignee_id': 'someuse'}}]}}, 'path': 'assignments_nested'}}, {'bool': { 'should': [{'nested': {'query': {'bool': { 'should': [{'term': {'assignments_nested.is_completed': 'true'}}, {'term': {'assignments_nested.is_completed': 'brayan'}}], 'minimum_should_match': 1 }}, 'path': 'assignments_nested'}}], 'minimum_should_match': 1}}]}}]}}
def test_range_query_with_missed_from_and_to(self): query_string = '(x:[_missing_ TO 2016-10-18T02:59:59] OR z:[_missing_ TO 2016-10-18T02:59:59]) AND (schedules.end_date:[2016-10-11T03:00:00 TO _missing_] AND schedules.obj_status:active)' params = {'es_q': query_string} result = compile_es_query(params) assert result == {'bool': {'must': [{'bool': { 'must': [{ 'bool': { 'should': [{ 'range': {'x': { 'lte': '2016-10-18T02:59:59'}}}, { 'range': {'z': { 'lte': '2016-10-18T02:59:59'}}}], 'minimum_should_match': 1 }}, { 'bool': { 'must': [{ 'nested': {'query': {'bool': { 'must': [{ 'range': {'schedules_nested.end_date': { 'gte': '2016-10-11T03:00:00'}}}, {'term': {'schedules_nested.obj_status': 'active'}}]}}, 'path': 'schedules_nested'}}]}}]}}]}}
def build_search_params(self, params): params = dictset(params) _params = dict( index=self.index_name, doc_type=self.doc_type ) _raw_terms = params.pop('q', '') if 'body' not in params and 'es_q' not in params: analyzed_terms = apply_analyzer(params, self.doc_type, engine.get_document_cls) query_string = self.build_qs(params.remove(RESERVED_PARAMS), _raw_terms) query = {'must': []} if query_string: query['must'].append({'query_string': {'query': query_string}}) if analyzed_terms: query['must'].append(analyzed_terms) if query['must']: _params['body'] = {'query': {'bool': query}} else: _params['body'] = {'query': {'match_all': {}}} if 'body' in params: raise JHTTPUnprocessableEntity('Illegal parameter "body"') if '_limit' not in params: params['_limit'] = self.api.count(index=self.index_name)['count'] _params['from_'], _params['size'] = process_limit( params.get('_start', None), params.get('_page', None), params['_limit']) if 'es_q' in params: _params['body'] = {} try: _params['body']['query'] = compile_es_query(params) except Exception as exc: log.exception('es_q parsing error: {exc}'.format(exc=exc)) raise JHTTPBadRequest('Bad query string for {params}' .format( params=_params['body']['query']['query_string']['query'])) log.debug('Parsed ES request body {body}'.format(body=_params['body']['query'])) if '_sort' in params and self.proxy: params['_sort'] = substitute_nested_terms(params['_sort'], self.proxy.substitutions) if '_sort' in params: _params['sort'] = apply_sort(params['_sort']) if '_fields' in params: params['_fields'] = self.add_nested_fields(params['_fields'], ',') _params['fields'] = params['_fields'] if '_search_fields' in params: search_fields = params['_search_fields'].split(',') search_fields.reverse() # Substitute search fields and add ^index for index, search_field in enumerate(search_fields): sf_terms = search_field.split('.') if self.proxy is not None: if len(sf_terms) > 0 and sf_terms[0] in self.proxy.substitutions: sf_terms[0] += "_nested" search_field = '.'.join(sf_terms) search_fields[index] = search_field + '^' + str(index + 1) must_query = _params['body']['query']['bool']['must'] query_string = {} for query_item in must_query: if 'query_string' in query_item: query_string = query_item break current_qs = query_string.get('query_string', None) if current_qs: query_string['query_string']['fields'] = search_fields return _params