schon/core/elasticsearch/documents.py
Egor fureunoir Gorbunov 97829d23a6 Features: 1) Add suggest, price, and quantity fields to ProductDocument; 2) Introduce prepare_suggest method for enhancing autocomplete functionality; 3) Enhance search with filters, function scoring, and result aggregation; 4) Add new analyzers and token filters for synonyms and stopwords.
Fixes: 1) Remove unused imports in `core/elasticsearch/__init__.py`.

Extra: Refactor `process_query` for improved readability and functionality; update aggregation and result processing logic; reformat and clean up code.
2025-06-20 03:55:56 +03:00

125 lines
3.5 KiB
Python

from django_elasticsearch_dsl import Document, fields
from django_elasticsearch_dsl.registries import registry
from core.elasticsearch import COMMON_ANALYSIS, ActiveOnlyMixin, _add_multilang_fields
from core.models import Brand, Category, Product
class _BaseDoc(ActiveOnlyMixin, Document):
name = fields.TextField(
attr="name",
analyzer="standard",
fields={
"raw": fields.KeywordField(ignore_above=256),
"ngram": fields.TextField(
analyzer="name_ngram", search_analyzer="query_lc"
),
"phonetic": fields.TextField(analyzer="name_phonetic"),
"auto": fields.TextField(
analyzer="autocomplete", search_analyzer="autocomplete_search"
),
},
)
description = fields.TextField(
attr="description",
analyzer="standard",
fields={
"raw": fields.KeywordField(ignore_above=256),
"ngram": fields.TextField(
analyzer="name_ngram", search_analyzer="query_lc"
),
"phonetic": fields.TextField(analyzer="name_phonetic"),
"auto": fields.TextField(
analyzer="autocomplete", search_analyzer="autocomplete_search"
),
},
)
slug = fields.KeywordField(attr="slug", index=False)
class Index:
settings = {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": COMMON_ANALYSIS,
"index": {"max_ngram_diff": 20},
}
def prepare_name(self, instance):
return getattr(instance, "name", "") or ""
def prepare_description(self, instance):
return getattr(instance, "description", "") or ""
class ProductDocument(_BaseDoc):
suggest = fields.CompletionField(
analyzer="autocomplete",
search_analyzer="autocomplete_search",
)
price = fields.FloatField(attr="price")
quantity = fields.IntegerField(attr="quantity")
rating = fields.FloatField(attr="rating")
class Index(_BaseDoc.Index):
name = "products"
class Django:
model = Product
fields = ["uuid"]
def prepare_suggest(self, instance):
terms = [instance.name]
if instance.brand:
terms.append(instance.brand.name)
terms.append(instance.category.name)
return {"input": terms, "weight": int(instance.quantity)}
_add_multilang_fields(ProductDocument)
registry.register_document(ProductDocument)
class CategoryDocument(_BaseDoc):
class Index(_BaseDoc.Index):
name = "categories"
class Django:
model = Category
fields = ["uuid"]
_add_multilang_fields(CategoryDocument)
registry.register_document(CategoryDocument)
class BrandDocument(ActiveOnlyMixin, Document):
name = fields.TextField(
attr="name",
analyzer="standard",
fields={
"raw": fields.KeywordField(ignore_above=256),
"ngram": fields.TextField(
analyzer="name_ngram", search_analyzer="query_lc"
),
"phonetic": fields.TextField(analyzer="name_phonetic"),
},
)
class Index:
name = "brands"
settings = {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": COMMON_ANALYSIS,
"index": {"max_ngram_diff": 18},
}
class Django:
model = Brand
fields = ["uuid"]
def prepare_name(self, instance):
return getattr(instance, "name", "") or ""
registry.register_document(BrandDocument)