Another agg ES response strategy
This commit is contained in:
parent
9b02b855d6
commit
68626e9fd5
|
|
@ -1,7 +1,48 @@
|
||||||
"""Search indexes filters."""
|
"""Search indexes filters."""
|
||||||
from elasticsearch_dsl.query import Q
|
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 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):
|
class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,25 @@ from search_indexes.documents.product import ProductDocument
|
||||||
from utils.pagination import ESDocumentPagination
|
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."""
|
"""News document ViewSet."""
|
||||||
|
|
||||||
document = NewsDocument
|
document = NewsDocument
|
||||||
|
|
@ -26,7 +44,7 @@ class NewsDocumentViewSet(BaseDocumentViewSet):
|
||||||
filter_backends = [
|
filter_backends = [
|
||||||
filters.CustomSearchFilterBackend,
|
filters.CustomSearchFilterBackend,
|
||||||
FilteringFilterBackend,
|
FilteringFilterBackend,
|
||||||
FacetedSearchFilterBackend,
|
filters.CustomFacetedSearchFilterBackend,
|
||||||
]
|
]
|
||||||
|
|
||||||
faceted_search_fields = {
|
faceted_search_fields = {
|
||||||
|
|
@ -86,7 +104,7 @@ class MobileNewsDocumentViewSet(NewsDocumentViewSet):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
class EstablishmentDocumentViewSet(BaseDocumentViewSet, FacetedResponseMixin):
|
||||||
"""Establishment document ViewSet."""
|
"""Establishment document ViewSet."""
|
||||||
|
|
||||||
document = EstablishmentDocument
|
document = EstablishmentDocument
|
||||||
|
|
@ -103,7 +121,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
FilteringFilterBackend,
|
FilteringFilterBackend,
|
||||||
filters.CustomSearchFilterBackend,
|
filters.CustomSearchFilterBackend,
|
||||||
GeoSpatialFilteringFilterBackend,
|
GeoSpatialFilteringFilterBackend,
|
||||||
FacetedSearchFilterBackend,
|
filters.CustomFacetedSearchFilterBackend,
|
||||||
]
|
]
|
||||||
|
|
||||||
faceted_search_fields = {
|
faceted_search_fields = {
|
||||||
|
|
@ -306,7 +324,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
|
||||||
filter_backends = [
|
filter_backends = [
|
||||||
FilteringFilterBackend,
|
FilteringFilterBackend,
|
||||||
filters.CustomSearchFilterBackend,
|
filters.CustomSearchFilterBackend,
|
||||||
FacetedSearchFilterBackend,
|
filters.CustomFacetedSearchFilterBackend,
|
||||||
]
|
]
|
||||||
|
|
||||||
search_fields = {
|
search_fields = {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from django.conf import settings
|
||||||
from rest_framework.pagination import CursorPagination, PageNumberPagination
|
from rest_framework.pagination import CursorPagination, PageNumberPagination
|
||||||
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination as ESPagination
|
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination as ESPagination
|
||||||
|
|
||||||
|
|
||||||
class ProjectPageNumberPagination(PageNumberPagination):
|
class ProjectPageNumberPagination(PageNumberPagination):
|
||||||
"""Customized pagination class."""
|
"""Customized pagination class."""
|
||||||
|
|
||||||
|
|
@ -65,6 +64,23 @@ class ESDocumentPagination(ESPagination):
|
||||||
return None
|
return None
|
||||||
return self.page.previous_page_number()
|
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):
|
class EstablishmentPortionPagination(ProjectMobilePagination):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user