Another agg ES response strategy
This commit is contained in:
parent
9b02b855d6
commit
68626e9fd5
|
|
@ -1,7 +1,48 @@
|
|||
"""Search indexes filters."""
|
||||
from elasticsearch_dsl.query import Q
|
||||
from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend
|
||||
from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend, FacetedSearchFilterBackend
|
||||
from search_indexes.utils import OBJECT_FIELD_PROPERTIES
|
||||
from six import iteritems
|
||||
|
||||
|
||||
class CustomFacetedSearchFilterBackend(FacetedSearchFilterBackend):
|
||||
|
||||
def __init__(self):
|
||||
self.facets_computed = {}
|
||||
|
||||
def aggregate(self, request, queryset, view):
|
||||
"""Aggregate.
|
||||
|
||||
:param request:
|
||||
:param queryset:
|
||||
:param view:
|
||||
:return:
|
||||
"""
|
||||
def makefilter(cur_facet):
|
||||
def myfilter(x):
|
||||
return cur_facet['facet']._params['field'] != next(iter(x._params))
|
||||
return myfilter
|
||||
__facets = self.construct_facets(request, view)
|
||||
for __field, __facet in iteritems(__facets):
|
||||
agg = __facet['facet'].get_aggregation()
|
||||
agg_filter = Q('match_all')
|
||||
if __facet['global']:
|
||||
queryset.aggs.bucket(
|
||||
'_filter_' + __field,
|
||||
'global'
|
||||
).bucket(__field, agg)
|
||||
else:
|
||||
qs = queryset._clone()
|
||||
filterer = makefilter(__facet)
|
||||
qs.query._proxied._params['must'] = list(filter(filterer, qs.query._proxied._params['must']))
|
||||
facet_name = '_filter_' + __field
|
||||
qs.aggs.bucket(
|
||||
facet_name,
|
||||
'filter',
|
||||
filter=agg_filter
|
||||
).bucket(__field, agg)
|
||||
self.facets_computed.update({facet_name: qs.execute().aggregations[facet_name]})
|
||||
return queryset
|
||||
|
||||
|
||||
class CustomSearchFilterBackend(SearchFilterBackend):
|
||||
|
|
|
|||
|
|
@ -14,7 +14,25 @@ from search_indexes.documents.product import ProductDocument
|
|||
from utils.pagination import ESDocumentPagination
|
||||
|
||||
|
||||
class NewsDocumentViewSet(BaseDocumentViewSet):
|
||||
class FacetedResponseMixin:
|
||||
def filter_queryset(self, queryset):
|
||||
"""
|
||||
Given a queryset, filter it with whichever filter backend is in use.
|
||||
|
||||
You are unlikely to want to override this method, although you may need
|
||||
to call it either from a list view, or from a custom `get_object`
|
||||
method if you want to apply the configured filtering backend to the
|
||||
default queryset.
|
||||
"""
|
||||
for backend in list(self.filter_backends):
|
||||
bc = backend()
|
||||
queryset = bc.filter_queryset(self.request, queryset, self)
|
||||
if hasattr(bc, 'facets_computed'):
|
||||
setattr(self, 'facets_computed', bc.facets_computed)
|
||||
return queryset
|
||||
|
||||
|
||||
class NewsDocumentViewSet(BaseDocumentViewSet, FacetedResponseMixin):
|
||||
"""News document ViewSet."""
|
||||
|
||||
document = NewsDocument
|
||||
|
|
@ -26,7 +44,7 @@ class NewsDocumentViewSet(BaseDocumentViewSet):
|
|||
filter_backends = [
|
||||
filters.CustomSearchFilterBackend,
|
||||
FilteringFilterBackend,
|
||||
FacetedSearchFilterBackend,
|
||||
filters.CustomFacetedSearchFilterBackend,
|
||||
]
|
||||
|
||||
faceted_search_fields = {
|
||||
|
|
@ -86,7 +104,7 @@ class MobileNewsDocumentViewSet(NewsDocumentViewSet):
|
|||
]
|
||||
|
||||
|
||||
class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||
class EstablishmentDocumentViewSet(BaseDocumentViewSet, FacetedResponseMixin):
|
||||
"""Establishment document ViewSet."""
|
||||
|
||||
document = EstablishmentDocument
|
||||
|
|
@ -103,7 +121,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
|||
FilteringFilterBackend,
|
||||
filters.CustomSearchFilterBackend,
|
||||
GeoSpatialFilteringFilterBackend,
|
||||
FacetedSearchFilterBackend,
|
||||
filters.CustomFacetedSearchFilterBackend,
|
||||
]
|
||||
|
||||
faceted_search_fields = {
|
||||
|
|
@ -306,7 +324,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
|
|||
filter_backends = [
|
||||
FilteringFilterBackend,
|
||||
filters.CustomSearchFilterBackend,
|
||||
FacetedSearchFilterBackend,
|
||||
filters.CustomFacetedSearchFilterBackend,
|
||||
]
|
||||
|
||||
search_fields = {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ from django.conf import settings
|
|||
from rest_framework.pagination import CursorPagination, PageNumberPagination
|
||||
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination as ESPagination
|
||||
|
||||
|
||||
class ProjectPageNumberPagination(PageNumberPagination):
|
||||
"""Customized pagination class."""
|
||||
|
||||
|
|
@ -65,6 +64,23 @@ class ESDocumentPagination(ESPagination):
|
|||
return None
|
||||
return self.page.previous_page_number()
|
||||
|
||||
def get_facets(self, page=None):
|
||||
"""Get facets.
|
||||
|
||||
:param page:
|
||||
:return:
|
||||
"""
|
||||
if page is None:
|
||||
page = self.page
|
||||
|
||||
if hasattr(self, 'facets_computed'):
|
||||
ret = {}
|
||||
for filter_field, bucket_data in self.facets_computed.items():
|
||||
ret.update({filter_field: bucket_data.__dict__['_d_']})
|
||||
return ret
|
||||
elif hasattr(page, 'facets') and hasattr(page.facets, '_d_'):
|
||||
return page.facets._d_
|
||||
|
||||
|
||||
class EstablishmentPortionPagination(ProjectMobilePagination):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user