def contact_es_search(org, text, base_group=None, sort_struct=None): """ Returns ES query """ if not base_group: base_group = org.cached_all_contacts_group if not sort_struct: sort_field = "-id" else: if sort_struct["field_type"] == "field": sort_field = { sort_struct["field_path"]: { "order": sort_struct["sort_direction"], "nested": { "path": "fields", "filter": { "term": { "fields.field": sort_struct["field_uuid"] } } }, } } else: sort_field = { sort_struct["field_name"]: { "order": sort_struct["sort_direction"] } } es_filter = es_Q( "bool", filter=[ # es_Q('term', is_blocked=False), # es_Q('term', is_stopped=False), es_Q("term", org_id=org.id), es_Q("term", groups=str(base_group.uuid)), ], ) if text: parsed = parse_query(text, as_anon=org.is_anon) es_match = parsed.as_elasticsearch(org) else: parsed = None es_match = es_Q() return ( (ModelESSearch(model=Contact, index="contacts").params( routing=org.id).query(es_match & es_filter).sort(sort_field)), parsed, )
def contact_es_search(org, text, base_group=None, sort_struct=None): """ Returns ES query """ if not base_group: base_group = org.cached_all_contacts_group if not sort_struct: sort_field = "-id" else: if sort_struct["field_type"] == "field": sort_field = { sort_struct["field_path"]: { "order": sort_struct["sort_direction"], "nested": {"path": "fields", "filter": {"term": {"fields.field": sort_struct["field_uuid"]}}}, } } else: sort_field = {sort_struct["field_name"]: {"order": sort_struct["sort_direction"]}} es_filter = es_Q( "bool", filter=[ # es_Q('term', is_blocked=False), # es_Q('term', is_stopped=False), es_Q("term", org_id=org.id), es_Q("term", groups=str(base_group.uuid)), ], ) if text: parsed = parse_query(text, as_anon=org.is_anon) es_match = parsed.as_elasticsearch(org) else: parsed = None es_match = es_Q() return ( ( ModelESSearch(model=Contact, index="contacts") .params(routing=org.id) .query(es_match & es_filter) .sort(sort_field) ), parsed, )
def contact_es_search(org, text, base_group=None): """ Returns ES query """ if not base_group: base_group = org.cached_all_contacts_group es_filter = es_Q( 'bool', filter=[ # es_Q('term', is_blocked=False), # es_Q('term', is_stopped=False), es_Q('term', org_id=org.id), es_Q('term', groups=six.text_type(base_group.uuid)) ]) parsed = parse_query(text, as_anon=org.is_anon) es_match = parsed.as_elasticsearch(org) return (ModelESSearch(model=Contact, index='contacts').params( routing=org.id).query(es_match & es_filter).sort('-modified_on_mu')), parsed
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if self.comparator.lower() in self.IS_SET_LOOKUPS: is_set = True elif self.comparator.lower() in self.IS_NOT_SET_LOOKUPS: is_set = False else: raise SearchException(_("Invalid operator for empty string comparison")) if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) es_query = es_Q("term", **{"fields.field": field_uuid}) if field.value_type == Value.TYPE_TEXT: field_name = "fields.text" elif field.value_type == Value.TYPE_NUMBER: field_name = "fields.number" elif field.value_type == Value.TYPE_DATETIME: field_name = "fields.datetime" elif field.value_type == Value.TYPE_STATE: field_name = "fields.state" elif field.value_type == Value.TYPE_DISTRICT: field_name = "fields.district" elif field.value_type == Value.TYPE_WARD: field_name = "fields.ward" else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{field.value_type}'")) es_query &= es_Q("exists", **{"field": field_name}) if is_set: return es_Q("nested", path="fields", query=es_query) else: return ~es_Q("nested", path="fields", query=es_query) elif prop_type == ContactQuery.PROP_SCHEME: if org.is_anon: return es_Q("ids", **{"values": [-1]}) es_query = es_Q("exists", **{"field": "urns.path"}) & es_Q("term", **{"urns.scheme": field.lower()}) if is_set: return es_Q("nested", path="urns", query=es_query) else: return ~es_Q("nested", path="urns", query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: field_key = field.key if field_key == "name": if is_set: es_query = es_Q("exists", **{"field": "name"}) & ~es_Q("term", **{"name.keyword": ""}) else: es_query = ~(es_Q("exists", **{"field": "name"}) & ~es_Q("term", **{"name.keyword": ""})) return es_query elif field_key == "language": if is_set: es_query = es_Q("exists", **{"field": "language"}) & ~es_Q("term", **{"language": ""}) else: es_query = ~(es_Q("exists", **{"field": "language"}) & ~es_Q("term", **{"language": ""})) return es_query elif field_key == "id": raise SearchException(_("All contacts have an 'id', it's not possible to check if 'id' is set")) elif field_key == "created_on": raise SearchException( _("All contacts have a 'created_on', it's not possible to check if 'created_on' is set") ) else: # pragma: no cover raise SearchException(_(f"Unknown attribute field '{field}'")) else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{prop_type}'"))
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) es_query = es_Q("term", **{"fields.field": field_uuid}) if field.value_type == Value.TYPE_TEXT: query_value = self.value.lower() if self.comparator == "=": es_query &= es_Q("term", **{"fields.text": query_value}) elif self.comparator == "!=": es_query &= es_Q("term", **{"fields.text": query_value}) es_query &= es_Q("exists", **{"field": "fields.text"}) # search for the inverse of what was specified return ~es_Q("nested", path="fields", query=es_query) else: raise SearchException(_(f"Unknown text comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_NUMBER: query_value = str(self._parse_number(self.value)) if self.comparator == "=": es_query &= es_Q("match", **{"fields.number": query_value}) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.number": {"gt": query_value}}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.number": {"gte": query_value}}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.number": {"lt": query_value}}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.number": {"lte": query_value}}) else: raise SearchException(_(f"Unknown number comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_DATETIME: query_value = str_to_date(self.value, field.org.get_dayfirst()) if not query_value: raise SearchException(_(f"Unable to parse the date '{self.value}'")) # datetime contact values are serialized as ISO8601 timestamps in local time on ElasticSearch lower_bound, upper_bound = date_to_day_range_utc(query_value, org) if self.comparator == "=": es_query &= es_Q( "range", **{"fields.datetime": {"gte": lower_bound.isoformat(), "lt": upper_bound.isoformat()}} ) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.datetime": {"gte": upper_bound.isoformat()}}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.datetime": {"gte": lower_bound.isoformat()}}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.datetime": {"lt": lower_bound.isoformat()}}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.datetime": {"lt": upper_bound.isoformat()}}) else: raise SearchException(_(f"Unknown datetime comparator: '{self.comparator}'")) elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT, Value.TYPE_WARD): query_value = self.value.lower() if field.value_type == Value.TYPE_WARD: field_name = "fields.ward" elif field.value_type == Value.TYPE_DISTRICT: field_name = "fields.district" elif field.value_type == Value.TYPE_STATE: field_name = "fields.state" else: # pragma: no cover raise SearchException(_(f"Unknown location type: '{field.value_type}'")) if self.comparator == "=": field_name += "_keyword" es_query &= es_Q("term", **{field_name: query_value}) elif self.comparator == "!=": field_name += "_keyword" es_query &= es_Q("term", **{field_name: query_value}) es_query &= es_Q("exists", **{"field": field_name}) return ~es_Q("nested", path="fields", query=es_query) else: raise SearchException(_(f"Unsupported comparator '{self.comparator}' for location field")) else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{field.value_type}'")) return es_Q("nested", path="fields", query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: query_value = self.value.lower() field_key = field.key if field_key == "name": if self.comparator == "=": field_name = "name.keyword" es_query = es_Q("term", **{field_name: query_value}) elif self.comparator == "~": field_name = "name" es_query = es_Q("match", **{field_name: query_value}) elif self.comparator == "!=": field_name = "name.keyword" es_query = ~es_Q("term", **{field_name: query_value}) else: raise SearchException(_(f"Unknown attribute comparator: '{self.comparator}'")) elif field_key == "id": es_query = es_Q("ids", **{"values": [query_value]}) elif field_key == "language": if self.comparator == "=": field_name = "language" es_query = es_Q("term", **{field_name: query_value}) elif self.comparator == "!=": field_name = "language" es_query = ~es_Q("term", **{field_name: query_value}) else: raise SearchException(_(f"Unknown attribute comparator: '{self.comparator}'")) elif field_key == "created_on": query_value = str_to_date(self.value, field.org.get_dayfirst()) if not query_value: raise SearchException(_(f"Unable to parse the date '{self.value}'")) # contact created_on is serialized as ISO8601 timestamp in utc time on ElasticSearch lower_bound, upper_bound = date_to_day_range_utc(query_value, org) if self.comparator == "=": es_query = es_Q( "range", **{"created_on": {"gte": lower_bound.isoformat(), "lt": upper_bound.isoformat()}} ) elif self.comparator == ">": es_query = es_Q("range", **{"created_on": {"gte": upper_bound.isoformat()}}) elif self.comparator == ">=": es_query = es_Q("range", **{"created_on": {"gte": lower_bound.isoformat()}}) elif self.comparator == "<": es_query = es_Q("range", **{"created_on": {"lt": lower_bound.isoformat()}}) elif self.comparator == "<=": es_query = es_Q("range", **{"created_on": {"lt": upper_bound.isoformat()}}) else: raise SearchException(_(f"Unknown created_on comparator: '{self.comparator}'")) else: # pragma: no cover raise SearchException(_(f"Unknown attribute field '{field}'")) return es_query elif prop_type == ContactQuery.PROP_SCHEME: query_value = self.value.lower() es_query = es_Q("term", **{"urns.scheme": field.lower()}) if org.is_anon: return es_Q("ids", **{"values": [-1]}) else: if self.comparator == "=": es_query &= es_Q("term", **{"urns.path.keyword": query_value}) elif self.comparator == "~": es_query &= es_Q("match_phrase", **{"urns.path": query_value}) else: raise SearchException(_(f"Unknown scheme comparator: '{self.comparator}'")) return es_Q("nested", path="urns", query=es_query) else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{prop_type}'"))
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) es_query = es_Q("term", **{"fields.field": field_uuid}) if field.value_type == Value.TYPE_TEXT: query_value = self.value.lower() if self.comparator == "=": es_query &= es_Q("term", **{"fields.text": query_value}) else: raise SearchException( _(f"Unknown text comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_NUMBER: query_value = str(self._parse_number(self.value)) if self.comparator == "=": es_query &= es_Q("match", **{"fields.number": query_value}) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.number": { "gt": query_value }}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.number": { "gte": query_value }}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.number": { "lt": query_value }}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.number": { "lte": query_value }}) else: raise SearchException( _(f"Unknown number comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_DATETIME: utc_range = calculate_utc_range(org, self.value) if self.comparator == "=": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[0].isoformat(), "lt": utc_range[1].isoformat() } }, ) elif self.comparator == ">": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[1].isoformat() } }) elif self.comparator == ">=": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[0].isoformat() } }) elif self.comparator == "<": es_query &= es_Q( "range", **{ "fields.datetime": { "lt": utc_range[0].isoformat() } }) elif self.comparator == "<=": es_query &= es_Q( "range", **{ "fields.datetime": { "lt": utc_range[1].isoformat() } }) else: raise SearchException( _(f"Unknown datetime comparator: '{self.comparator}'")) elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT, Value.TYPE_WARD): query_value = self.value.lower() if field.value_type == Value.TYPE_WARD: field_name = "fields.ward" elif field.value_type == Value.TYPE_DISTRICT: field_name = "fields.district" elif field.value_type == Value.TYPE_STATE: field_name = "fields.state" else: # pragma: no cover raise SearchException( _(f"Unknown location type: '{field.value_type}'")) if self.comparator == "=": field_name += "_keyword" es_query &= es_Q("term", **{field_name: query_value}) else: raise SearchException( _(f"Unsupported comparator '{self.comparator}' for location field" )) else: # pragma: no cover raise SearchException( _(f"Unrecognized contact field type '{field.value_type}'")) return es_Q("nested", path="fields", query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: query_value = self.value.lower() field_key = field.key if field_key == "name": if self.comparator == "=": field_name = "name.keyword" es_query = es_Q("term", **{field_name: query_value}) elif self.comparator == "~": field_name = "name" es_query = es_Q("match", **{field_name: query_value}) else: raise SearchException( _(f"Unknown attribute comparator: '{self.comparator}'") ) elif field_key == "id": es_query = es_Q("ids", **{"values": [query_value]}) elif field_key == "language": if self.comparator == "=": field_name = "language" es_query = es_Q("term", **{field_name: query_value}) else: raise SearchException( _(f"Unknown attribute comparator: '{self.comparator}'") ) elif field_key == "created_on": utc_range = calculate_utc_range(org, self.value) if self.comparator == "=": es_query = es_Q( "range", **{ "created_on": { "gte": utc_range[0].isoformat(), "lt": utc_range[1].isoformat() } }) elif self.comparator == ">": es_query = es_Q( "range", **{"created_on": { "gte": utc_range[1].isoformat() }}) elif self.comparator == ">=": es_query = es_Q( "range", **{"created_on": { "gte": utc_range[0].isoformat() }}) elif self.comparator == "<": es_query = es_Q( "range", **{"created_on": { "lt": utc_range[0].isoformat() }}) elif self.comparator == "<=": es_query = es_Q( "range", **{"created_on": { "lt": utc_range[1].isoformat() }}) else: raise SearchException( _(f"Unknown created_on comparator: '{self.comparator}'" )) else: # pragma: no cover raise SearchException(_(f"Unknown attribute field '{field}'")) return es_query elif prop_type == ContactQuery.PROP_SCHEME: query_value = self.value.lower() es_query = es_Q("term", **{"urns.scheme": field.lower()}) if org.is_anon: return es_Q("ids", **{"values": [-1]}) else: if self.comparator == "=": es_query &= es_Q("term", **{"urns.path.keyword": query_value}) elif self.comparator == "~": es_query &= es_Q("match_phrase", **{"urns.path": query_value}) else: raise SearchException( _(f"Unknown scheme comparator: '{self.comparator}'")) return es_Q("nested", path="urns", query=es_query) else: # pragma: no cover raise SearchException( _(f"Unrecognized contact field type '{prop_type}'"))
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) es_query = es_Q("term", **{"fields.field": field_uuid}) if field.value_type == Value.TYPE_TEXT: query_value = self.value.lower() if self.comparator == "=": es_query &= es_Q("term", **{"fields.text": query_value}) else: raise SearchException( _("Unknown text comparator: '%s'") % (self.comparator, )) elif field.value_type == Value.TYPE_NUMBER: query_value = str(self._parse_number(self.value)) if self.comparator == "=": es_query &= es_Q("match", **{"fields.number": query_value}) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.number": { "gt": query_value }}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.number": { "gte": query_value }}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.number": { "lt": query_value }}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.number": { "lte": query_value }}) else: raise SearchException( _("Unknown number comparator: '%s'") % (self.comparator, )) elif field.value_type == Value.TYPE_DATETIME: query_value = str_to_datetime(self.value, field.org.timezone, field.org.get_dayfirst(), fill_time=False) if not query_value: raise SearchException( _("Unable to parse the date '%s'") % self.value) utc_range = date_to_utc_range(query_value.date(), field.org) if self.comparator == "=": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[0].isoformat(), "lt": utc_range[1].isoformat() } }) elif self.comparator == ">": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[1].isoformat() } }) elif self.comparator == ">=": es_query &= es_Q( "range", **{ "fields.datetime": { "gte": utc_range[0].isoformat() } }) elif self.comparator == "<": es_query &= es_Q( "range", **{ "fields.datetime": { "lt": utc_range[0].isoformat() } }) elif self.comparator == "<=": es_query &= es_Q( "range", **{ "fields.datetime": { "lt": utc_range[1].isoformat() } }) else: raise SearchException( _("Unknown datetime comparator: '%s'") % (self.comparator, )) elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT, Value.TYPE_WARD): query_value = self.value.lower() if field.value_type == Value.TYPE_WARD: field_name = "fields.ward" elif field.value_type == Value.TYPE_DISTRICT: field_name = "fields.district" elif field.value_type == Value.TYPE_STATE: field_name = "fields.state" else: # pragma: no cover raise SearchException( _("Unknown location type: '%s'") % (field.value_type, )) if self.comparator == "=": field_name += "_keyword" es_query &= es_Q("term", **{field_name: query_value}) else: raise SearchException( _("Unsupported comparator '%s' for location field") % self.comparator) else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % field.value_type) return es_Q("nested", path="fields", query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: query_value = self.value.lower() if field == "name": if self.comparator == "=": field_name = "name.keyword" es_query = es_Q("term", **{field_name: query_value}) elif self.comparator == "~": field_name = "name" es_query = es_Q("match", **{field_name: query_value}) else: raise SearchException( _("Unknown attribute comparator: '%s'") % (self.comparator, )) elif field == "id": es_query = es_Q("ids", **{"values": [query_value]}) else: # pragma: no cover raise SearchException( _("Unknown attribute field '%s'") % (field, )) return es_query elif prop_type == ContactQuery.PROP_SCHEME: query_value = self.value.lower() es_query = es_Q("term", **{"urns.scheme": field.lower()}) if org.is_anon: return es_Q("ids", **{"values": [-1]}) else: if self.comparator == "=": es_query &= es_Q("term", **{"urns.path.keyword": query_value}) elif self.comparator == "~": es_query &= es_Q("match_phrase", **{"urns.path": query_value}) else: raise SearchException( _("Unknown scheme comparator: '%s'") % (self.comparator, )) return es_Q("nested", path="urns", query=es_query) else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % prop_type)
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if self.comparator.lower() in self.IS_SET_LOOKUPS: is_set = True elif self.comparator.lower() in self.IS_NOT_SET_LOOKUPS: is_set = False else: raise SearchException( _("Invalid operator for empty string comparison")) if prop_type == ContactQuery.PROP_FIELD: field_uuid = six.text_type(field.uuid) es_query = es_Q('term', **{'fields.field': field_uuid}) if field.value_type == Value.TYPE_TEXT: field_name = 'fields.text' elif field.value_type == Value.TYPE_NUMBER: field_name = 'fields.number' elif field.value_type == Value.TYPE_DATETIME: field_name = 'fields.datetime' elif field.value_type == Value.TYPE_STATE: field_name = 'fields.state' elif field.value_type == Value.TYPE_DISTRICT: field_name = 'fields.district' elif field.value_type == Value.TYPE_WARD: field_name = 'fields.ward' else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % (field.value_type, )) es_query &= es_Q('exists', **{'field': field_name}) if is_set: return es_Q('nested', path='fields', query=es_query) else: return ~es_Q('nested', path='fields', query=es_query) elif prop_type == ContactQuery.PROP_SCHEME: if org.is_anon: return es_Q('ids', **{'values': [-1]}) es_query = es_Q('exists', **{'field': 'urns.path'}) & es_Q( 'term', **{'urns.scheme': field.lower()}) if is_set: return es_Q('nested', path='urns', query=es_query) else: return ~es_Q('nested', path='urns', query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: if field == 'name': if is_set: es_query = es_Q('exists', **{ 'field': 'name' }) & ~es_Q('term', **{'name.keyword': ''}) else: es_query = ~(es_Q('exists', **{'field': 'name'}) & ~es_Q('term', **{'name.keyword': ''})) return es_query elif field == 'id': raise SearchException( "All contacts have an ID, you cannot check if 'id' is set") else: # pragma: no cover raise SearchException( _("Unknown attribute field '%s'") % (field, )) else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % (prop_type, ))
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = six.text_type(field.uuid) es_query = es_Q('term', **{'fields.field': field_uuid}) if field.value_type == Value.TYPE_TEXT: query_value = self.value.lower() if self.comparator == '=': es_query &= es_Q('term', **{'fields.text': query_value}) else: raise SearchException( _("Unknown text comparator: '%s'") % (self.comparator, )) elif field.value_type == Value.TYPE_NUMBER: query_value = six.text_type(self._parse_number(self.value)) if self.comparator == '=': es_query &= es_Q('match', **{'fields.number': query_value}) elif self.comparator == '>': es_query &= es_Q('range', **{'fields.number': { 'gt': query_value }}) elif self.comparator == '>=': es_query &= es_Q('range', **{'fields.number': { 'gte': query_value }}) elif self.comparator == '<': es_query &= es_Q('range', **{'fields.number': { 'lt': query_value }}) elif self.comparator == '<=': es_query &= es_Q('range', **{'fields.number': { 'lte': query_value }}) else: raise SearchException( _("Unknown number comparator: '%s'") % (self.comparator, )) elif field.value_type == Value.TYPE_DATETIME: query_value = str_to_datetime(self.value, field.org.timezone, field.org.get_dayfirst(), fill_time=False) if not query_value: raise SearchException( _("Unable to parse the date '%s'") % self.value) utc_range = date_to_utc_range(query_value.date(), field.org) if self.comparator == '=': es_query &= es_Q( 'range', **{ 'fields.datetime': { 'gte': utc_range[0].isoformat(), 'lt': utc_range[1].isoformat() } }) elif self.comparator == '>': es_query &= es_Q( 'range', **{ 'fields.datetime': { 'gte': utc_range[1].isoformat() } }) elif self.comparator == '>=': es_query &= es_Q( 'range', **{ 'fields.datetime': { 'gte': utc_range[0].isoformat() } }) elif self.comparator == '<': es_query &= es_Q( 'range', **{ 'fields.datetime': { 'lt': utc_range[0].isoformat() } }) elif self.comparator == '<=': es_query &= es_Q( 'range', **{ 'fields.datetime': { 'lt': utc_range[1].isoformat() } }) else: raise SearchException( _("Unknown datetime comparator: '%s'") % (self.comparator, )) elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT, Value.TYPE_WARD): query_value = self.value.lower() if field.value_type == Value.TYPE_WARD: field_name = 'fields.ward' elif field.value_type == Value.TYPE_DISTRICT: field_name = 'fields.district' elif field.value_type == Value.TYPE_STATE: field_name = 'fields.state' else: # pragma: no cover raise SearchException( _("Unknown location type: '%s'") % (field.value_type, )) if self.comparator == '=': field_name += '.keyword' es_query &= es_Q('term', **{field_name: query_value}) else: raise SearchException( _("Unsupported comparator '%s' for location field") % self.comparator) else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % field.value_type) return es_Q('nested', path='fields', query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: query_value = self.value.lower() if field == 'name': if self.comparator == '=': field_name = 'name.keyword' es_query = es_Q('term', **{field_name: query_value}) elif self.comparator == '~': field_name = 'name' es_query = es_Q('match', **{field_name: query_value}) else: raise SearchException( _("Unknown attribute comparator: '%s'") % (self.comparator, )) elif field == 'id': es_query = es_Q('ids', **{'values': [query_value]}) else: # pragma: no cover raise SearchException( _("Unknown attribute field '%s'") % (field, )) return es_query elif prop_type == ContactQuery.PROP_SCHEME: query_value = self.value.lower() es_query = es_Q('term', **{'urns.scheme': field.lower()}) if org.is_anon: return es_Q('ids', **{'values': [-1]}) else: if self.comparator == '=': es_query &= es_Q('term', **{'urns.path.keyword': query_value}) elif self.comparator == '~': es_query &= es_Q('match_phrase', **{'urns.path': query_value}) else: raise SearchException( _("Unknown scheme comparator: '%s'") % (self.comparator, )) return es_Q('nested', path='urns', query=es_query) else: # pragma: no cover raise SearchException( _("Unrecognized contact field type '%s'") % prop_type)
def as_elasticsearch(self, org, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) es_query = es_Q("term", **{"fields.field": field_uuid}) if field.value_type == Value.TYPE_TEXT: query_value = self.value.lower() if self.comparator == "=": es_query &= es_Q("term", **{"fields.text": query_value}) else: raise SearchException(_(f"Unknown text comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_NUMBER: query_value = str(self._parse_number(self.value)) if self.comparator == "=": es_query &= es_Q("match", **{"fields.number": query_value}) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.number": {"gt": query_value}}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.number": {"gte": query_value}}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.number": {"lt": query_value}}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.number": {"lte": query_value}}) else: raise SearchException(_(f"Unknown number comparator: '{self.comparator}'")) elif field.value_type == Value.TYPE_DATETIME: utc_range = calculate_utc_range(org, self.value) if self.comparator == "=": es_query &= es_Q( "range", **{"fields.datetime": {"gte": utc_range[0].isoformat(), "lt": utc_range[1].isoformat()}}, ) elif self.comparator == ">": es_query &= es_Q("range", **{"fields.datetime": {"gte": utc_range[1].isoformat()}}) elif self.comparator == ">=": es_query &= es_Q("range", **{"fields.datetime": {"gte": utc_range[0].isoformat()}}) elif self.comparator == "<": es_query &= es_Q("range", **{"fields.datetime": {"lt": utc_range[0].isoformat()}}) elif self.comparator == "<=": es_query &= es_Q("range", **{"fields.datetime": {"lt": utc_range[1].isoformat()}}) else: raise SearchException(_(f"Unknown datetime comparator: '{self.comparator}'")) elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT, Value.TYPE_WARD): query_value = self.value.lower() if field.value_type == Value.TYPE_WARD: field_name = "fields.ward" elif field.value_type == Value.TYPE_DISTRICT: field_name = "fields.district" elif field.value_type == Value.TYPE_STATE: field_name = "fields.state" else: # pragma: no cover raise SearchException(_(f"Unknown location type: '{field.value_type}'")) if self.comparator == "=": field_name += "_keyword" es_query &= es_Q("term", **{field_name: query_value}) else: raise SearchException(_(f"Unsupported comparator '{self.comparator}' for location field")) else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{field.value_type}'")) return es_Q("nested", path="fields", query=es_query) elif prop_type == ContactQuery.PROP_ATTRIBUTE: query_value = self.value.lower() field_key = field.key if field_key == "name": if self.comparator == "=": field_name = "name.keyword" es_query = es_Q("term", **{field_name: query_value}) elif self.comparator == "~": field_name = "name" es_query = es_Q("match", **{field_name: query_value}) else: raise SearchException(_(f"Unknown attribute comparator: '{self.comparator}'")) elif field_key == "id": es_query = es_Q("ids", **{"values": [query_value]}) elif field_key == "language": if self.comparator == "=": field_name = "language" es_query = es_Q("term", **{field_name: query_value}) else: raise SearchException(_(f"Unknown attribute comparator: '{self.comparator}'")) elif field_key == "created_on": utc_range = calculate_utc_range(org, self.value) if self.comparator == "=": es_query = es_Q( "range", **{"created_on": {"gte": utc_range[0].isoformat(), "lt": utc_range[1].isoformat()}} ) elif self.comparator == ">": es_query = es_Q("range", **{"created_on": {"gte": utc_range[1].isoformat()}}) elif self.comparator == ">=": es_query = es_Q("range", **{"created_on": {"gte": utc_range[0].isoformat()}}) elif self.comparator == "<": es_query = es_Q("range", **{"created_on": {"lt": utc_range[0].isoformat()}}) elif self.comparator == "<=": es_query = es_Q("range", **{"created_on": {"lt": utc_range[1].isoformat()}}) else: raise SearchException(_(f"Unknown created_on comparator: '{self.comparator}'")) else: # pragma: no cover raise SearchException(_(f"Unknown attribute field '{field}'")) return es_query elif prop_type == ContactQuery.PROP_SCHEME: query_value = self.value.lower() es_query = es_Q("term", **{"urns.scheme": field.lower()}) if org.is_anon: return es_Q("ids", **{"values": [-1]}) else: if self.comparator == "=": es_query &= es_Q("term", **{"urns.path.keyword": query_value}) elif self.comparator == "~": es_query &= es_Q("match_phrase", **{"urns.path": query_value}) else: raise SearchException(_(f"Unknown scheme comparator: '{self.comparator}'")) return es_Q("nested", path="urns", query=es_query) else: # pragma: no cover raise SearchException(_(f"Unrecognized contact field type '{prop_type}'"))