From 2840370c3ef81173767c9887026a0cce8a5cbeb2 Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Fri, 20 Jun 2025 05:26:03 +0300 Subject: [PATCH] Features: 1) Add `priority` field to Brand model to support ranking functionality; 2) Enhance ProductDocument with `brand_priority` field in Elasticsearch for improved sorting; 3) Integrate function score query with `brand_priority` in Elasticsearch search logic; Fixes: None; Extra: 1) Update migrations for Brand model changes; 2) Refactor Elasticsearch query logic for clarity; --- core/elasticsearch/__init__.py | 21 ++++++++++-- core/elasticsearch/documents.py | 6 ++++ .../0027_brand_priority_alter_brand_slug.py | 32 +++++++++++++++++++ core/models.py | 7 ++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 core/migrations/0027_brand_priority_alter_brand_slug.py diff --git a/core/elasticsearch/__init__.py b/core/elasticsearch/__init__.py index 473f93af..898cc6ac 100644 --- a/core/elasticsearch/__init__.py +++ b/core/elasticsearch/__init__.py @@ -45,7 +45,7 @@ def process_query(query: str = "", request: Request | None = None): query = query.strip() try: - q = Q( + query_base = Q( "bool", should=[ Q( @@ -65,9 +65,26 @@ def process_query(query: str = "", request: Request | None = None): minimum_should_match=1, ) + function_score_query = Q( + "function_score", + query=query_base, + functions=[ + { + "filter": Q("term", **{"_index": "products"}), + "field_value_factor": { + "field": "brand_priority", + "factor": 1, + "modifier": "log1p", + "missing": 0, + }, + } + ], + boost_mode="sum", + ) + search = ( Search(index=["products", "categories", "brands", "posts"]) - .query(q) + .query(function_score_query) .extra(size=100) ) response = search.execute() diff --git a/core/elasticsearch/documents.py b/core/elasticsearch/documents.py index 4a2c895e..d373e81b 100644 --- a/core/elasticsearch/documents.py +++ b/core/elasticsearch/documents.py @@ -53,6 +53,12 @@ class _BaseDoc(ActiveOnlyMixin, Document): class ProductDocument(_BaseDoc): rating = fields.FloatField(attr="rating") + brand_priority = fields.IntegerField( + attr="brand.priority", + null=True, + index=True, + fields={"raw": fields.KeywordField()}, + ) class Index(_BaseDoc.Index): name = "products" diff --git a/core/migrations/0027_brand_priority_alter_brand_slug.py b/core/migrations/0027_brand_priority_alter_brand_slug.py new file mode 100644 index 00000000..0aca9c40 --- /dev/null +++ b/core/migrations/0027_brand_priority_alter_brand_slug.py @@ -0,0 +1,32 @@ +# Generated by Django 5.2 on 2025-06-20 02:25 + +import django_extensions.db.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0026_brand_slug_alter_category_slug_alter_product_slug"), + ] + + operations = [ + migrations.AddField( + model_name="brand", + name="priority", + field=models.PositiveIntegerField(default=0, verbose_name="brand priority"), + ), + migrations.AlterField( + model_name="brand", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + null=True, + populate_from=("name",), + unique=True, + verbose_name="brand slug", + ), + ), + ] diff --git a/core/models.py b/core/models.py index 6a02fcca..bcedb6c6 100644 --- a/core/models.py +++ b/core/models.py @@ -287,6 +287,13 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): unique=True, editable=False, null=True, + verbose_name=_("brand slug"), + ) + priority: int = PositiveIntegerField( + default=0, + null=False, + blank=False, + verbose_name=_("brand priority"), ) def __str__(self):