def calculate_utc_range(org, input_value): """ Calculates datetime range in UTC, we use it to check date containment """ query_value = str_to_datetime(input_value, org.timezone, org.get_dayfirst(), fill_time=False) if not query_value: raise SearchException(_(f"Unable to parse the date '{input_value}'")) return date_to_utc_range(query_value.date(), org)
def _build_datetime_field_params(self, field): lookup = self.DATETIME_LOOKUPS.get(self.comparator) if not lookup: raise SearchException( _("Can't query date fields with %s") % self.comparator) # parse as localized date local_date = str_to_datetime(self.value, field.org.timezone, field.org.get_dayfirst(), fill_time=False) if not local_date: raise SearchException( _("Unable to parse the date %s") % self.value) # get the range of UTC datetimes for this local date utc_range = date_to_utc_range(local_date.date(), field.org) if lookup == '<equal>': return { 'contact_field': field, 'datetime_value__gte': utc_range[0], 'datetime_value__lt': utc_range[1] } elif lookup == 'lt': return {'contact_field': field, 'datetime_value__lt': utc_range[0]} elif lookup == 'lte': return {'contact_field': field, 'datetime_value__lt': utc_range[1]} elif lookup == 'gt': return { 'contact_field': field, 'datetime_value__gte': utc_range[1] } elif lookup == 'gte': return { 'contact_field': field, 'datetime_value__gte': utc_range[0] }
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 evaluate(self, contact_json, prop_map): prop_type, field = prop_map[self.prop] if prop_type == ContactQuery.PROP_FIELD: field_uuid = str(field.uuid) contact_fields = contact_json.get("fields") if field_uuid not in contact_fields: return False if field.value_type == Value.TYPE_TEXT: query_value = self.value.upper() contact_value = contact_fields.get(field_uuid).get( "text").upper() if self.comparator == "=": return contact_value == query_value else: raise SearchException( _("Unknown text comparator: '%s'") % (self.comparator, )) elif field.value_type == Value.TYPE_NUMBER: query_value = self._parse_number(self.value) number_value = contact_fields.get(field_uuid).get( "number", contact_fields.get(field_uuid).get("decimal")) if number_value is None: return False contact_value = self._parse_number(number_value) if self.comparator == "=": return contact_value == query_value elif self.comparator == ">": return contact_value > query_value elif self.comparator == ">=": return contact_value >= query_value elif self.comparator == "<": return contact_value < query_value elif self.comparator == "<=": return contact_value <= 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) datetime_value = contact_fields.get(field_uuid).get("datetime") if datetime_value is None: return False contact_value = str_to_datetime(datetime_value, field.org.timezone) utc_range = date_to_utc_range(query_value.date(), field.org) if self.comparator == "=": return contact_value >= utc_range[ 0] and contact_value < utc_range[1] elif self.comparator == ">": return contact_value >= utc_range[1] elif self.comparator == ">=": return contact_value >= utc_range[0] elif self.comparator == "<": return contact_value < utc_range[0] elif self.comparator == "<=": return contact_value < utc_range[1] 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.upper() if field.value_type == Value.TYPE_WARD: ward_value = contact_fields.get(field_uuid).get("ward") if ward_value is None: ward_value = "" contact_value = ward_value.upper().split(" > ")[-1] elif field.value_type == Value.TYPE_DISTRICT: district_value = contact_fields.get(field_uuid).get( "district") if district_value is None: district_value = "" contact_value = district_value.upper().split(" > ")[-1] elif field.value_type == Value.TYPE_STATE: state_value = contact_fields.get(field_uuid).get("state") if state_value is None: state_value = "" contact_value = state_value.upper().split(" > ")[-1] else: # pragma: no cover raise SearchException( _("Unknown location type: '%s'") % (field.value_type, )) if self.comparator == "=": return contact_value == 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) elif prop_type == ContactQuery.PROP_SCHEME: for urn in contact_json.get("urns"): if urn.get("scheme") == field: contact_value = urn.get("path").upper() query_value = self.value.upper() if self.comparator == "=": if contact_value == query_value: return True elif self.comparator == "~": if query_value in contact_value: return True else: raise SearchException( _("Unknown urn scheme comparator: '%s'") % (self.comparator, )) return False else: 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)