From 0552d919f18d6fe579d6f25eb0958096184f798b Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 22 Jan 2020 18:43:51 +0300 Subject: [PATCH] BO news via ES #1 --- apps/news/filters.py | 2 +- apps/news/models.py | 24 +++++++++++++++++++++++- apps/search_indexes/utils.py | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/apps/news/filters.py b/apps/news/filters.py index a56463c5..3385c537 100644 --- a/apps/news/filters.py +++ b/apps/news/filters.py @@ -51,7 +51,7 @@ class NewsListFilterSet(filters.FilterSet): if value not in EMPTY_VALUES: if len(value) < 3: raise ValidationError({'detail': _('Type at least 3 characters to search please.')}) - return queryset.trigram_search(value) + return queryset.es_search(value) return queryset def in_tags(self, queryset, name, value): diff --git a/apps/news/models.py b/apps/news/models.py index 983cc9c2..5eef5a02 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -1,6 +1,7 @@ """News app models.""" import uuid +import elasticsearch_dsl from django.conf import settings from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes.models import ContentType @@ -159,8 +160,29 @@ class NewsQuerySet(TranslationQuerysetMixin): def by_locale(self, locale): return self.filter(title__icontains=locale) + def es_search(self, search_value: str): + from search_indexes.documents import NewsDocument + from search_indexes.utils import OBJECT_FIELD_PROPERTIES + search_value = search_value.lower() + search_fields = ('description', 'title', 'subtitle') + search_keys = [] + for field in search_fields: + for locale in OBJECT_FIELD_PROPERTIES.keys(): + search_keys.append(f'{field}.{locale}') + _query = None + for key in search_keys: + if _query is None: + _query = elasticsearch_dsl.Q('fuzzy', **{key: {'value': f'*{search_value}*', 'fuzziness': 'auto:2,5', + 'prefix_length': 0, 'max_expansions': 100}}) + else: + _query |= elasticsearch_dsl.Q('fuzzy', **{key: {'value': f'*{search_value}*', 'fuzziness': 'auto:2,5', + 'prefix_length': 0, 'max_expansions': 100}}) + search = NewsDocument.search().filter(_query)[0:10000].execute() + ids = [result.meta.id for result in search] + return self.filter(id__in=ids) + def trigram_search(self, search_value: str): - """Search with mistakes by name or last name.""" + """Search with mistakes by description or title or subtitle.""" return self.annotate( description_str=Cast('description', models.TextField()), title_str=Cast('title', models.TextField()), diff --git a/apps/search_indexes/utils.py b/apps/search_indexes/utils.py index d4c4f68a..52e0adb1 100644 --- a/apps/search_indexes/utils.py +++ b/apps/search_indexes/utils.py @@ -2,7 +2,7 @@ from django_elasticsearch_dsl import fields from utils.models import get_current_locale, get_default_locale -FACET_MAX_RESPONSE = 9999999 # Unlimited +FACET_MAX_RESPONSE = 9999999 # Unlimited ALL_LOCALES_LIST = [ 'hr-HR',