Example #1
0
    def execute_query(
        self, es_search: es_dsl.Search, *, from_: int = 0, size: Optional[int] = None
    ) -> Dict:
        if from_ is None:
            raise ValueError("'from_' must have a value.")

        response = {"hits": {"hits": [], "total": 0}}

        if size is None or (from_ + size > search_settings.scan_limit):
            # tmp_search = es_search.extra(from_=0, size=0)
            # tmp_response = tmp_search.execute()
            # tot_hits = tmp_response.hits.total
            tot_hits = es_search.count()
            response["hits"]["total"] = tot_hits
            if size is None:
                size = tot_hits - from_
            if tot_hits < from_:
                return response

        if size + from_ <= search_settings.scan_limit:
            extra_kwargs = {}
            if from_ is not None:
                extra_kwargs["from_"] = from_
            if size is not None:
                extra_kwargs["size"] = size
            if extra_kwargs:
                es_search = es_search.extra(**extra_kwargs)
            return es_search.execute().to_dict()
        else:
            es_search = es_search.params(preserve_order=True, scroll="5m")
            # Workaround
            scan_iter = elasticsearch.helpers.scan(
                es_search._using,
                query=es_search.to_dict(),
                index=es_search._index,
                doc_type=es_search._get_doc_type(),
                **es_search._params,
            )
            # scan_iter = es_search.scan()
            for hit in itertools.islice(scan_iter, from_, from_ + size):
                response["hits"]["hits"].append(hit)
                # response["hits"]["hits"].append(hit.to_dict())

            return response