Example #1
0
    def facet(self, field_name):
        # Get field
        field = self.query_compiler._get_filterable_field(field_name)
        if field is None:
            raise FilterFieldError(
                'Cannot facet search results with field "' + field_name +
                '". Please add index.FilterField(\'' + field_name + '\') to ' +
                self.query_compiler.queryset.model.__name__ +
                '.search_fields.',
                field_name=field_name)

        # Build body
        body = self._get_es_body()
        column_name = self.query_compiler.mapping.get_field_column_name(field)

        body['aggregations'] = {
            field_name: {
                'terms': {
                    'field': column_name,
                }
            }
        }

        # Send to Elasticsearch
        response = self.backend.es.search(
            index=self.backend.get_index_for_model(
                self.query_compiler.queryset.model).name,
            body=body,
            size=0,
        )

        return OrderedDict([
            (bucket['key'], bucket['doc_count'])
            for bucket in response['aggregations'][field_name]['buckets']
        ])
Example #2
0
    def facet(self, field_name):
        # Get field
        field = self.query_compiler._get_filterable_field(field_name)
        if field is None:
            raise FilterFieldError(
                'Cannot facet search results with field "' + field_name +
                '". Please add index.FilterField(\'' + field_name + '\') to ' +
                self.query_compiler.queryset.model.__name__ +
                '.search_fields.',
                field_name=field_name)

        query = self.query_compiler.search(self.backend.config, None, None)
        results = query.values(field_name).annotate(
            count=Count('pk')).order_by('-count')

        return OrderedDict([(result[field_name], result['count'])
                            for result in results])
Example #3
0
    def facet(self, field_name):
        # Get field
        field = self.query_compiler._get_filterable_field(field_name)
        if field is None:
            raise FilterFieldError(
                'Cannot facet search results with field "' + field_name +
                "\". Please add index.FilterField('" + field_name + "') to " +
                self.query_compiler.queryset.model.__name__ +
                ".search_fields.",
                field_name=field_name,
            )

        query = self.get_queryset()
        results = (query.values(field_name).annotate(
            count=Count("pk")).order_by("-count"))

        return OrderedDict([(result[field_name], result["count"])
                            for result in results])
Example #4
0
    def facet(self, field_name):
        # Get field
        field = self.query_compiler._get_filterable_field(field_name)
        if field is None:
            raise FilterFieldError(
                'Cannot facet search results with field "' + field_name +
                "\". Please add index.FilterField('" + field_name + "') to " +
                self.query_compiler.queryset.model.__name__ +
                ".search_fields.",
                field_name=field_name,
            )

        # Build body
        body = self._get_es_body()
        column_name = self.query_compiler.mapping.get_field_column_name(field)

        body["aggregations"] = {
            field_name: {
                "terms": {
                    "field": column_name,
                    "missing": 0,
                }
            }
        }

        # Send to Elasticsearch
        response = self.backend.es.search(
            index=self.backend.get_index_for_model(
                self.query_compiler.queryset.model).name,
            body=body,
            size=0,
        )

        return OrderedDict([
            (bucket["key"] if bucket["key"] != 0 else None,
             bucket["doc_count"])
            for bucket in response["aggregations"][field_name]["buckets"]
        ])
    def facets(self, *field_names):
        "Fetches facets from ES based on the fieldnames passed"
        aggregations = {}
        for field_path in field_names:
            field_match = FIELD_NAME_REGEX.match(field_path)
            if field_match is not None:
                field_name = field_match.group("field_name")

                # Get field
                field = self.query_compiler._get_filterable_field(  # pylint: disable=protected-access
                    field_name
                )
                if field is None:
                    raise FilterFieldError(
                        'Cannot facet search results with field "%(field_name)s". '
                        'Please add index.FilterField("%(field_name)s") to %(model_name)s.search_fields.'
                        % {
                            "field_name": field_name,
                            "model_name": self.query_compiler.queryset.model.__name__,
                        },
                        field_name=field_name,
                    )

                aggregations[field_path] = self._facet_to_aggregation(field_path)

        if aggregations:
            unfiltered_index = {
                "index": self.backend.get_index_for_model(
                    self.query_compiler.queryset.model
                ).name
            }
            unfiltered_body = {
                "query": self.query_compiler.get_unfiltered_query(),
                "size": 0,
            }
            unfiltered_body["aggregations"] = aggregations

            filtered_index = unfiltered_index
            filtered_body = {"query": self.query_compiler.get_query(), "size": 0}
            filtered_body["aggregations"] = aggregations

            multi_request = [
                unfiltered_index,
                unfiltered_body,
                filtered_index,
                filtered_body,
            ]

            # Send to Elasticsearch
            response = self.backend.es.msearch(body=multi_request)
            unfiltered_response, filtered_response = response["responses"]

            # handle errors gracefully
            if "error" in unfiltered_response:
                logger.error("Elasticsearch error %(error)s", unfiltered_response)
                return ({}, {})

            return (
                unfiltered_response["aggregations"],
                filtered_response["aggregations"],
            )

        return {}, {}