From 781e20eb9a1f0ab0355f3f4271eaeb413b1a962c Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Thu, 19 Jun 2025 17:54:34 +0300 Subject: [PATCH] Features: 1) Add typo-tolerant, multi-index search with phrase_prefix query; 2) Enhance query boost logic for name field; Fixes: 1) Avoid redundant nesting in slug determination; 2) Refactor image_url assignment to prevent repetition; Extra: Improve formatting and remove unnecessary dictionary structure in query functions. --- core/elasticsearch/__init__.py | 58 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/core/elasticsearch/__init__.py b/core/elasticsearch/__init__.py index efdc28c6..b84fcb6e 100644 --- a/core/elasticsearch/__init__.py +++ b/core/elasticsearch/__init__.py @@ -36,6 +36,9 @@ SMART_FIELDS = [ def process_query(query: str = "", request: Request | None = None): + """ + Perform a lenient, typo-tolerant, multi-index search + """ if not (query := query.strip()): raise ValueError(_("no search term provided.")) @@ -44,6 +47,12 @@ def process_query(query: str = "", request: Request | None = None): query=query, type="phrase_prefix", fields=[f for f in SMART_FIELDS if ".sat" in f], + boost=5, + ) + + phrase_prefix = Q( + "match_phrase_prefix", + **{"name": {"query": query, "boost": 6}} ) fuzzy_match = Q( @@ -63,15 +72,11 @@ def process_query(query: str = "", request: Request | None = None): combined = Q( "bool", - should=[sat_match, fuzzy_match, prefix_match], + should=[sat_match, phrase_prefix, fuzzy_match, prefix_match], minimum_should_match=1, ) functions = [ - { - "filter": Q("prefix", **{"name.raw": query.lower()}), - "weight": 5, - }, { "gauss": { "sales_rank": { @@ -110,9 +115,11 @@ def process_query(query: str = "", request: Request | None = None): obj_name = getattr(hit, "name", None) or getattr(hit, "title", None) or "N/A" raw_slug = getattr(hit, "slug", None) or "" obj_slug = ( - raw_slug or slugify(obj_name) + raw_slug + if raw_slug + else slugify(obj_name) if hit.meta.index in {"brands", "categories"} - else raw_slug + else "" ) image_url = None idx = hit.meta.index @@ -121,32 +128,23 @@ def process_query(query: str = "", request: Request | None = None): if idx == "products": prod = get_object_or_404(Product, uuid=obj_uuid) first = prod.images.order_by("priority").first() - image_url = ( - request.build_absolute_uri(first.image.url) - if first and first.image - else None - ) - if idx == "brands": + if first and first.image: + image_url = request.build_absolute_uri(first.image.url) + elif idx == "brands": brand = get_object_or_404(Brand, uuid=obj_uuid) - image_url = ( - request.build_absolute_uri(brand.small_logo.url) - if brand.small_logo - else None - ) - if idx == "categories": + if brand.small_logo: + image_url = request.build_absolute_uri(brand.small_logo.url) + elif idx == "categories": cat = get_object_or_404(Category, uuid=obj_uuid) - image_url = ( - request.build_absolute_uri(cat.image.url) if cat.image else None - ) + if cat.image: + image_url = request.build_absolute_uri(cat.image.url) - results[idx].append( - { - "uuid": str(obj_uuid), - "name": obj_name, - "slug": obj_slug, - "image": image_url, - } - ) + results[idx].append({ + "uuid": str(obj_uuid), + "name": obj_name, + "slug": obj_slug, + "image": image_url, + }) return results