def _apply_agg(self, search_query): exclude_tags = {self.qf._name} if self._conj_operator == QueryFilter.CONJ_OR: exclude_tags.add(self.name) filters = self._get_agg_filters( search_query.get_context().iter_post_filters_with_meta(), exclude_tags ) terms_agg = agg.Nested(path=self.path, aggs={ self._filter_key_agg_name: agg.Filter( self.key_expression, aggs={ self._filter_value_agg_name: agg.Terms( self.value_field, instance_mapper=self._instance_mapper, **self._agg_kwargs ) }, **self._agg_kwargs ) }) if filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*filters), aggs={self._agg_name: terms_agg} ) } else: aggs = {self._agg_name: terms_agg} return search_query.aggregations(**aggs)
def _get_group_values(self, search_query, post_filters, pagination_agg): if post_filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*post_filters), aggs={self._pagination_agg_name: pagination_agg} ) } else: aggs = {self._pagination_agg_name: pagination_agg} sq = ( search_query .with_search_type('count') .aggs(None) .aggs(**aggs) ) pagination_agg_res = self._get_pagination_agg_result(sq.result) self._process_pagination_agg(pagination_agg_res) values = [ group_bucket.key for group_bucket in pagination_agg_res.buckets ] offset = self._get_offset() return values[offset:offset + self.per_page]
def _apply_agg(self, search_query): if self.selected: return search_query agg_filters = search_query.get_context().post_filters return search_query.aggregations( **{ self._agg_name: agg.Filter( Bool.must(*chain(agg_filters, [self._condition]))) })
def _get_expression(self, params): values = self._get_values_from_params(params.get(self.alias, {})) if not values: return None if len(values) == 1: return self.field == values[0] if self._conj_operator == QueryFilter.CONJ_AND: return Bool.must(*(self.field == v for v in values)) else: return self.field.in_(values)
def _get_expression(self, params): values = self._get_values_from_params(params.get(self.alias, {})) if not values: return None if len(values) == 1: return Nested( path=self.path, query=Bool.must( self.key_expression, self.value_field == values[0] ) ) expressions = [self.key_expression] if self._conj_operator == QueryFilter.CONJ_AND: expressions.extend([self.value_field == v for v in values]) else: expressions.append(self.value_field.in_(values)) return Nested( path=self.path, query=Bool.must(*expressions) )
def _apply_filter(self, search_query, params): params = params.get(self.alias) or {} self.from_value = self._get_from_value(params) self.to_value = self._get_to_value(params) if self.from_value is None and self.to_value is None: return search_query expr = Nested( path=self.path, query=Bool.must( self.key_expression, self.value_field.range(gte=self.from_value, lte=self.to_value), ) ) return search_query.post_filter(expr, meta={'tags': {self.name}})
def test_weight(): assert Weight(3).to_elastic() == {"weight": 3} assert Weight(2, filter=Bool.must( PostDocument.status.in_([0, 1]), PostDocument.created_date >= 'now/d-7d') ).to_elastic() == { "weight": 2, "filter": { "bool": { "must": [ {"terms": {"status": [0, 1]}}, {"range": {"created_date": {"gte": "now/d-7d"}}} ] } } }
def _apply_agg(self, search_query): order_aggs, order_by = self._extract_orders(search_query) group_agg = agg.Terms( self.group_by, size=self.per_page, order=order_by, aggs=dict( {self._top_hits_agg_name: agg.TopHits(**self.group_kwargs)}, **order_aggs ) ) pagination_agg = agg.Terms( self.group_by, size=self.max_items, order=order_by, aggs=order_aggs, ) post_filters = list(search_query.get_context().iter_post_filters()) if self.page == 1: page_aggs = { self._agg_name: group_agg, self._pagination_agg_name: pagination_agg, } else: group_values = self._get_group_values(search_query, post_filters, pagination_agg) post_filters.append(self.group_by.in_(group_values)) page_aggs={ self._agg_name: group_agg, } if post_filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*post_filters), aggs=page_aggs ) } else: aggs = page_aggs search_query = search_query.aggs(aggs) return search_query
def _apply_agg(self, search_query): filters = self._get_agg_filters( search_query.get_context().iter_post_filters_with_meta(), {self.qf._name, self.name} ) aggs = {} if self._compute_enabled: aggs.update({ self._enabled_agg_name: agg.Nested( path=self.path, aggs={ self._filter_key_agg_name: agg.Filter( self.key_expression, aggs={ self._filter_value_agg_name: agg.Filter( self.value_field != None ) } ) } ) }) if self._compute_min_max: stat_aggs = { self._enabled_agg_name_stat: agg.Nested( path=self.path, aggs={ self._filter_key_agg_name: agg.Filter( self.key_expression, aggs={ self._min_agg_name: agg.Min(self.value_field), self._max_agg_name: agg.Max(self.value_field), } ) } ) } if filters: aggs.update({ self._filter_agg_name: agg.Filter(Bool.must(*filters), aggs=stat_aggs) }) else: aggs.update(stat_aggs) return search_query.aggregations(**aggs)
def _apply_agg(self, search_query): exclude_tags = {self.qf._name} if self._conj_operator == QueryFilter.CONJ_OR: exclude_tags.add(self.name) filters = self._get_agg_filters( search_query.iter_post_filters_with_meta(), exclude_tags ) terms_agg = agg.Terms(self.field, instance_mapper=self._instance_mapper, **self._agg_kwargs) if filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*filters), aggs={self._agg_name: terms_agg} ) } else: aggs = {self._agg_name: terms_agg} return search_query.aggregations(**aggs)
def _apply_agg(self, search_query): exclude_tags = {self.qf._name} if self._conj_operator == QueryFilter.CONJ_OR: exclude_tags.add(self.name) filters = self._get_agg_filters( search_query.get_context().iter_post_filters_with_meta(), exclude_tags ) additional_filters = self._filters or [] terms_agg = agg.Terms(self.field, instance_mapper=self._instance_mapper, **self._agg_kwargs) if filters or additional_filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*(filters + additional_filters)), aggs={self._agg_name: terms_agg} ) } else: aggs = {self._agg_name: terms_agg} return search_query.aggregations(**aggs)
def _apply_agg(self, search_query): exclude_tags = {self.qf._name} if self._conj_operator == QueryFilter.CONJ_OR: exclude_tags.add(self.name) filters = self._get_agg_filters( search_query.get_context().iter_post_filters_with_meta(), exclude_tags ) filter_aggs = {} for fv in self.values: filter_aggs[self._make_agg_name(fv.value)] = agg.Filter(fv.expr, **self.agg_kwargs) if filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*filters), aggs=filter_aggs ) } else: aggs = filter_aggs return search_query.aggregations(**aggs)
def _get_expression(self, params): values = params.get(self.alias, {}).get('exact') if not values: if self.default: values = [[self.default]] if not values: return None expressions = [] for v in values: w = v[0] filter_value = self.get_value(w) if filter_value and not isinstance(filter_value.expr, MatchAll): expressions.append(filter_value.expr) if not expressions: return None if self._conj_operator == QueryFilter.CONJ_AND: return Bool.must(*expressions) else: return Bool.should(*expressions)
def _apply_agg(self, search_query): exclude_tags = {self.qf._name} if self._conj_operator == QueryFilter.CONJ_OR: exclude_tags.add(self.name) filters = self._get_agg_filters( search_query.iter_post_filters_with_meta(), exclude_tags ) filter_aggs = {} for fv in self.values: filter_aggs[self._make_agg_name(fv.value)] = agg.Filter(fv.expr, **self.agg_kwargs) if filters: aggs = { self._filter_agg_name: agg.Filter( Bool.must(*filters), aggs=filter_aggs ) } else: aggs = filter_aggs return search_query.aggregations(**aggs)
def _apply_agg(self, search_query): filters = self._get_agg_filters( search_query.iter_post_filters_with_meta(), {self.qf._name, self.name} ) aggs = {} if self._compute_enabled: aggs.update({ self._enabled_agg_name: agg.Filter(self.field != None), }) if self._compute_min_max: stat_aggs = { self._min_agg_name: agg.Min(self.field), self._max_agg_name: agg.Max(self.field), } if filters: aggs.update({ self._filter_agg_name: agg.Filter(Bool.must(*filters), aggs=stat_aggs) }) else: aggs.update(stat_aggs) return search_query.aggregations(**aggs)
def _get_filter_expression(self, attr_id: int, values: ParamValues) -> t.Optional[Expression]: gte = self._parse_last_value(values, 'gte') gte_value = None if gte is not None: gte_value = merge_attr_value_float(attr_id, gte) lte = self._parse_last_value(values, 'lte') lte_value = None if lte is not None: lte_value = merge_attr_value_float(attr_id, lte) if gte is not None and lte is not None: if gte >= 0.0 and lte >= 0.0: return Range(self.field, gte=gte_value, lte=lte_value) elif gte < 0.0 and lte < 0.0: return Range(self.field, gte=lte_value, lte=gte_value) elif gte < 0.0 and lte >= 0: return Bool.should( Range(self.field, gte=self._minus_zero(attr_id), lte=gte_value), Range(self.field, gte=self._plus_zero(attr_id), lte=lte_value), ) else: return Bool.must( Range(self.field, gte=gte_value, lte=self._plus_inf(attr_id)), Range(self.field, gte=lte_value, lte=self._minus_inf(attr_id)), ) if gte is not None: if gte >= 0.0: return Range(self.field, gte=gte_value, lte=self._plus_inf(attr_id)) else: return Bool.should( Range(self.field, gte=self._minus_zero(attr_id), lte=gte_value), Range(self.field, gte=self._plus_zero(attr_id), lte=self._plus_inf(attr_id)), ) if lte is not None: if lte < 0.0: return Range(self.field, gte=lte_value, lte=self._minus_inf(attr_id)) else: return Bool.should( Range(self.field, gte=self._plus_zero(attr_id), lte=lte_value), Range(self.field, gte=self._minus_zero(attr_id), lte=self._minus_inf(attr_id)), ) return None
def test_attr_bool_facet_filter__multiple_selected_values(bool_qf, compiler): sq = bool_qf.apply(SearchQuery(), {'a1': ['true', 'false'], 'a2': 'true'}) assert sq.to_dict(compiler=compiler) == (SearchQuery().aggs({ 'qf.attr_bool.filter': agg.Filter( Bool.must( Terms('attr.bool', [0b11, 0b10]), Term('attr.bool', 0b101), ), aggs={'qf.attr_bool': agg.Terms(Field('attr.bool'), size=100)}), 'qf.attr_bool.filter:1': agg.Filter(Term('attr.bool', 0b101), aggs={ 'qf.attr_bool:1': agg.Terms(Field('attr.bool'), size=2, include=[0b10, 0b11]) }), 'qf.attr_bool.filter:2': agg.Filter(Terms('attr.bool', [0b11, 0b10]), aggs={ 'qf.attr_bool:2': agg.Terms(Field('attr.bool'), size=2, include=[0b100, 0b101]) }), }).post_filter( Bool.must( Terms('attr.bool', [0b11, 0b10]), Term('attr.bool', 0b101), )).to_dict(compiler=compiler)) qf_res = bool_qf.process_result( SearchResult( { 'aggregations': { 'qf.attr_bool.filter': { 'doc_count': 200, 'qf.attr_bool': { 'buckets': [ { 'key': 0b11, 'doc_count': 123, }, { 'key': 0b101, 'doc_count': 1 }, ] } }, 'qf.attr_bool.filter:1': { 'doc_count': 163, 'qf.attr_bool:1': { 'buckets': [ { 'key': 0b11, 'doc_count': 123, }, { 'key': 0b10, 'doc_count': 99 }, ] } }, 'qf.attr_bool.filter:2': { 'doc_count': 144, 'qf.attr_bool:2': { 'buckets': [ { 'key': 0b101, 'doc_count': 1 }, ] } }, } }, aggregations=sq.get_context().aggregations)) assert len(qf_res.attr_bool.facets) == 2 facet = qf_res.attr_bool.get_facet(1) assert len(facet.all_values) == 2 assert len(facet.selected_values) == 2 assert len(facet.values) == 0 assert facet.all_values[0] is facet.selected_values[0] assert facet.all_values[1] is facet.selected_values[1] assert facet.all_values[0].value is True assert facet.all_values[0].count == 123 assert facet.all_values[0].count_text == '123' assert facet.all_values[0].selected is True assert facet.all_values[1].value is False assert facet.all_values[1].count == 99 assert facet.all_values[1].count_text == '99' assert facet.all_values[1].selected is True facet = qf_res.attr_bool.get_facet(2) assert len(facet.all_values) == 1 assert len(facet.selected_values) == 1 assert len(facet.values) == 0 assert facet.all_values[0] is facet.selected_values[0] assert facet.all_values[0].value is True assert facet.all_values[0].count == 1 assert facet.all_values[0].count_text == '1' assert facet.all_values[0].selected is True