Features: 1) Add SearchAsYouTypeField to name field in ProductDocument for improved search capabilities; 2) Introduce product_type and sales_rank fields to ProductDocument with preparation methods; 3) Add total_orders property to model for calculating product order count;

Fixes: 1) Enhance `raw` field in `name` with `lc` normalizer for consistent lowercase processing;

Extra: 1) Define custom `lc` normalizer in Elasticsearch settings; 2) General code formatting and minor cleanup.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-19 14:27:57 +03:00
parent ac39dedf94
commit 432e4bf110
3 changed files with 18 additions and 2 deletions

View file

@ -183,6 +183,7 @@ COMMON_ANALYSIS = {
}, },
"query_lc": {"tokenizer": "standard", "filter": ["lowercase", "asciifolding"]}, "query_lc": {"tokenizer": "standard", "filter": ["lowercase", "asciifolding"]},
}, },
"normalizer": {"lc": {"type": "custom", "filter": ["lowercase", "asciifolding"]}},
} }

View file

@ -1,4 +1,4 @@
from django_elasticsearch_dsl import Document, fields from django_elasticsearch_dsl import Document, SearchAsYouTypeField, fields
from django_elasticsearch_dsl.registries import registry from django_elasticsearch_dsl.registries import registry
from core.elasticsearch import COMMON_ANALYSIS, ActiveOnlyMixin, _add_multilang_fields from core.elasticsearch import COMMON_ANALYSIS, ActiveOnlyMixin, _add_multilang_fields
@ -10,7 +10,8 @@ class _BaseDoc(ActiveOnlyMixin, Document):
attr="name", attr="name",
analyzer="standard", analyzer="standard",
fields={ fields={
"raw": fields.KeywordField(ignore_above=256), "raw": fields.KeywordField(ignore_above=256, normalizer="lc"),
"sat": SearchAsYouTypeField(max_shingle_size=4),
"ngram": fields.TextField( "ngram": fields.TextField(
analyzer="name_ngram", search_analyzer="query_lc" analyzer="name_ngram", search_analyzer="query_lc"
), ),
@ -53,6 +54,14 @@ class _BaseDoc(ActiveOnlyMixin, Document):
class ProductDocument(_BaseDoc): class ProductDocument(_BaseDoc):
rating = fields.FloatField(attr="rating") rating = fields.FloatField(attr="rating")
product_type = fields.KeywordField()
sales_rank = fields.IntegerField()
def prepare_product_type(self, obj):
return obj.category.slug.split("-")[0] if obj.category else "other"
def prepare_sales_rank(self, obj):
return obj.total_orders or 0
class Index(_BaseDoc.Index): class Index(_BaseDoc.Index):
name = "products" name = "products"

View file

@ -404,6 +404,12 @@ class Product(ExportModelOperationsMixin("product"), NiceModel):
cache.set(cache_key, quantity, 3600) cache.set(cache_key, quantity, 3600)
return quantity return quantity
@property
def total_orders(self):
return OrderProduct.objects.filter(
order__status="FINISHED", product__uuid=self.uuid
).count()
class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): class Attribute(ExportModelOperationsMixin("attribute"), NiceModel):
is_publicly_visible = True is_publicly_visible = True