def search(request, domain): """ Accepts search criteria as GET params, e.g. "https://www.commcarehq.org/a/domain/phone/search/?a=b&c=d" Returns results as a fixture with the same structure as a casedb instance. """ criteria = request.GET.dict() try: case_type = criteria.pop('case_type') except KeyError: return HttpResponse('Search request must specify case type', status=400) try: case_search_criteria = CaseSearchCriteria(domain, case_type, criteria) search_es = case_search_criteria.search_es except QueryMergeException as e: return _handle_query_merge_exception(request, e) try: hits = search_es.run().raw_hits except Exception as e: return _handle_es_exception( request, e, case_search_criteria.query_addition_debug_details) # Even if it's a SQL domain, we just need to render the hits as cases, so CommCareCase.wrap will be fine cases = [ CommCareCase.wrap(flatten_result(result, include_score=True)) for result in hits ] fixtures = CaseDBFixture(cases).fixture return HttpResponse(fixtures, content_type="text/xml; charset=utf-8")
def app_aware_search(request, domain, app_id): """ Accepts search criteria as GET params, e.g. "https://www.commcarehq.org/a/domain/phone/search/?a=b&c=d" Returns results as a fixture with the same structure as a casedb instance. """ criteria = request.GET.dict() try: case_type = criteria.pop('case_type') except KeyError: return HttpResponse('Search request must specify case type', status=400) try: case_search_criteria = CaseSearchCriteria(domain, case_type, criteria) except TooManyRelatedCasesError: return HttpResponse(_('Search has too many results. Please try a more specific search.'), status=400) search_es = case_search_criteria.search_es try: hits = search_es.run().raw_hits except Exception as e: notify_exception(request, str(e), details=dict( exception_type=type(e), )) return HttpResponse(status=500) # Even if it's a SQL domain, we just need to render the hits as cases, so CommCareCase.wrap will be fine cases = [CommCareCase.wrap(flatten_result(result, include_score=True)) for result in hits] if app_id: cases.extend(get_related_cases(domain, app_id, case_type, cases)) fixtures = CaseDBFixture(cases).fixture return HttpResponse(fixtures, content_type="text/xml; charset=utf-8")
def test_add_blacklisted_ids(self): criteria = { "commcare_blacklisted_owner_ids": "id1 id2 id3,id4" } expected = {'query': {'filtered': {'filter': {'and': [ {'term': {'domain.exact': 'swashbucklers'}}, {"term": {"type.exact": "case_type"}}, {"term": {"closed": False}}, {'not': {'term': {'owner_id': 'id1'}}}, {'not': {'term': {'owner_id': 'id2'}}}, {'not': {'term': {'owner_id': 'id3,id4'}}}, {'match_all': {}} ]}, "query": { "match_all": {} }}}, 'size': CASE_SEARCH_MAX_RESULTS} self.checkQuery( CaseSearchCriteria(DOMAIN, 'case_type', criteria).search_es, expected )
def test_date_range_criteria(self): config, _ = CaseSearchConfig.objects.get_or_create(pk=self.domain, enabled=True) self._assert_query_runs_correctly( self.domain, [ { '_id': 'c1', 'dob': date(2020, 3, 1) }, { '_id': 'c2', 'dob': date(2020, 3, 2) }, { '_id': 'c3', 'dob': date(2020, 3, 3) }, { '_id': 'c4', 'dob': date(2020, 3, 4) }, ], CaseSearchCriteria(self.domain, self.case_type, { 'dob': '__range__2020-03-02__2020-03-03' }).search_es, None, ['c2', 'c3']) config.delete()
def test_add_blacklisted_ids(self): criteria = {"commcare_blacklisted_owner_ids": "id1 id2 id3,id4"} expected = { "query": { "bool": { "filter": [{ 'term': { 'domain.exact': 'swashbucklers' } }, { "term": { "type.exact": "case_type" } }, { "term": { "closed": False } }, { "bool": { "must_not": { "term": { "owner_id": "id1" } } } }, { "bool": { "must_not": { "term": { "owner_id": "id2" } } } }, { "bool": { "must_not": { "term": { "owner_id": "id3,id4" } } } }, { "match_all": {} }], "must": { "match_all": {} } } }, "size": CASE_SEARCH_MAX_RESULTS } self.checkQuery( CaseSearchCriteria(DOMAIN, 'case_type', criteria).search_es, expected)
def test_add_ignore_pattern_queries(self): rc = IgnorePatterns( domain=DOMAIN, case_type='case_type', case_property='name', regex=' word', ) # remove ' word' from the name case property rc.save() self.config.ignore_patterns.add(rc) rc = IgnorePatterns( domain=DOMAIN, case_type='case_type', case_property='name', regex=' gone', ) # remove ' gone' from the name case property rc.save() self.config.ignore_patterns.add(rc) rc = IgnorePatterns( domain=DOMAIN, case_type='case_type', case_property='special_id', regex='-', ) # remove '-' from the special id case property rc.save() self.config.ignore_patterns.add(rc) self.config.save() rc = IgnorePatterns( domain=DOMAIN, case_type='case_type', case_property='phone_number', regex='+', ) # remove '+' from the phone_number case property rc.save() self.config.ignore_patterns.add(rc) self.config.save() criteria = OrderedDict([ ('phone_number', '+91999'), ('special_id', 'abc-123-546'), ('name', "this word should be gone"), ('other_name', "this word should not be gone"), ]) expected = { "query": { "filtered": { "filter": { "and": [{ "term": { "domain.exact": "swashbucklers" } }, { "term": { "type.exact": "case_type" } }, { "term": { "closed": False } }, { "match_all": {} }] }, "query": { "bool": { "must": [{ "nested": { "path": "case_properties", "query": { "filtered": { "filter": { "and": ({ "term": { "case_properties.key.exact": "phone_number" } }, { "term": { "case_properties.value.exact": "91999" } }), }, "query": { "match_all": {} } } } } }, { "nested": { "path": "case_properties", "query": { "filtered": { "filter": { "and": ({ "term": { "case_properties.key.exact": "special_id" } }, { "term": { "case_properties.value.exact": "abc123546" } }) }, "query": { "match_all": {} } } } } }, { "nested": { "path": "case_properties", "query": { "filtered": { "filter": { "and": ({ "term": { "case_properties.key.exact": "name" } }, { "term": { "case_properties.value.exact": "this should be" } }) }, "query": { "match_all": {} } } } } }, { "nested": { "path": "case_properties", "query": { "filtered": { "filter": { "and": ({ "term": { "case_properties.key.exact": "other_name" } }, { "term": { "case_properties.value.exact": ("this word should not be gone" ) } }) }, "query": { "match_all": {} } } } } }] } } } }, "size": CASE_SEARCH_MAX_RESULTS, } self.checkQuery( CaseSearchCriteria(DOMAIN, 'case_type', criteria).search_es, expected, )