From b326d7b8fd72d1ad3d009e30e5e40d82f5d9e2bb Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Mon, 9 Sep 2019 12:00:53 +0300 Subject: [PATCH] Overrided searchfilterbackend --- apps/search_indexes/filters.py | 82 ++++++++++++++++++++++++++++++++++ apps/search_indexes/views.py | 36 ++++++--------- 2 files changed, 96 insertions(+), 22 deletions(-) create mode 100644 apps/search_indexes/filters.py diff --git a/apps/search_indexes/filters.py b/apps/search_indexes/filters.py new file mode 100644 index 00000000..f9ae0ef1 --- /dev/null +++ b/apps/search_indexes/filters.py @@ -0,0 +1,82 @@ +"""Search indexes filters.""" +from elasticsearch_dsl.query import Q +from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend +from utils.models import get_current_language + + +class CustomSearchFilterBackend(SearchFilterBackend): + """Custom SearchFilterBackend.""" + + @staticmethod + def get_field_name(view, field): + field_name = field + if hasattr(view, 'search_fields') and hasattr(view, 'translated_search_fields'): + if field in view.translated_search_fields: + field_name = f'{field}.{get_current_language()}' + return field_name + + def construct_search(self, request, view): + """Construct search. + + We have to deal with two types of structures: + + Type 1: + + >>> search_fields = ( + >>> 'title', + >>> 'description', + >>> 'summary', + >>> ) + + Type 2: + + >>> search_fields = { + >>> 'title': {'boost': 2}, + >>> 'description': None, + >>> 'summary': None, + >>> } + + :param request: Django REST framework request. + :param queryset: Base queryset. + :param view: View. + :type request: rest_framework.request.Request + :type queryset: elasticsearch_dsl.search.Search + :type view: rest_framework.viewsets.ReadOnlyModelViewSet + :return: Updated queryset. + :rtype: elasticsearch_dsl.search.Search + """ + query_params = self.get_search_query_params(request) + __queries = [] + for search_term in query_params: + __values = self.split_lookup_name(search_term, 1) + __len_values = len(__values) + if __len_values > 1: + field, value = __values + if field in view.search_fields: + # Initial kwargs for the match query + field_kwargs = {self.get_field_name(view, field): {'query': value}} + # In case if we deal with structure 2 + if isinstance(view.search_fields, dict): + extra_field_kwargs = view.search_fields[field] + if extra_field_kwargs: + field_kwargs[self.get_field_name(view, field)].update(extra_field_kwargs) + # The match query + __queries.append( + Q("match", **field_kwargs) + ) + else: + for field in view.search_fields: + # Initial kwargs for the match query + field_kwargs = {self.get_field_name(view, field): {'query': search_term}} + + # In case if we deal with structure 2 + if isinstance(view.search_fields, dict): + extra_field_kwargs = view.search_fields[field] + if extra_field_kwargs: + field_kwargs[self.get_field_name(view, field)].update(extra_field_kwargs) + + # The match query + __queries.append( + Q("match", **field_kwargs) + ) + return __queries \ No newline at end of file diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 4aad078c..46f5b902 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -2,22 +2,9 @@ from rest_framework import permissions from django_elasticsearch_dsl_drf.viewsets import BaseDocumentViewSet from django_elasticsearch_dsl_drf.pagination import PageNumberPagination -from search_indexes import serializers +from search_indexes import serializers, filters from search_indexes.documents import NewsDocument -# from django_elasticsearch_dsl_drf.constants import ( -# LOOKUP_QUERY_IN, -# LOOKUP_QUERY_GT, -# ) -# -from django_elasticsearch_dsl_drf.filter_backends import ( - FilteringFilterBackend, - IdsFilterBackend, - OrderingFilterBackend, - SearchFilterBackend, - DefaultOrderingFilterBackend, -) - class NewsDocumentViewSet(BaseDocumentViewSet): """News document ViewSet.""" @@ -28,13 +15,18 @@ class NewsDocumentViewSet(BaseDocumentViewSet): permission_classes = (permissions.AllowAny,) serializer_class = serializers.NewsDocumentSerializer ordering = ('id',) - # + filter_backends = [ - # DefaultOrderingFilterBackend, - # FilteringFilterBackend, - SearchFilterBackend, + filters.CustomSearchFilterBackend, ] - # - # search_fields = ( - # 'playlist', 'title', 'subtitle', 'description' - # ) \ No newline at end of file + + search_fields = ( + 'title', + 'subtitle', + 'description', + ) + translated_search_fields = ( + 'title', + 'subtitle', + 'description', + ) \ No newline at end of file