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.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-19 17:54:34 +03:00
parent ba335e5d96
commit 781e20eb9a

View file

@ -36,6 +36,9 @@ SMART_FIELDS = [
def process_query(query: str = "", request: Request | None = None): def process_query(query: str = "", request: Request | None = None):
"""
Perform a lenient, typo-tolerant, multi-index search
"""
if not (query := query.strip()): if not (query := query.strip()):
raise ValueError(_("no search term provided.")) raise ValueError(_("no search term provided."))
@ -44,6 +47,12 @@ def process_query(query: str = "", request: Request | None = None):
query=query, query=query,
type="phrase_prefix", type="phrase_prefix",
fields=[f for f in SMART_FIELDS if ".sat" in f], 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( fuzzy_match = Q(
@ -63,15 +72,11 @@ def process_query(query: str = "", request: Request | None = None):
combined = Q( combined = Q(
"bool", "bool",
should=[sat_match, fuzzy_match, prefix_match], should=[sat_match, phrase_prefix, fuzzy_match, prefix_match],
minimum_should_match=1, minimum_should_match=1,
) )
functions = [ functions = [
{
"filter": Q("prefix", **{"name.raw": query.lower()}),
"weight": 5,
},
{ {
"gauss": { "gauss": {
"sales_rank": { "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" obj_name = getattr(hit, "name", None) or getattr(hit, "title", None) or "N/A"
raw_slug = getattr(hit, "slug", None) or "" raw_slug = getattr(hit, "slug", None) or ""
obj_slug = ( obj_slug = (
raw_slug or slugify(obj_name) raw_slug
if raw_slug
else slugify(obj_name)
if hit.meta.index in {"brands", "categories"} if hit.meta.index in {"brands", "categories"}
else raw_slug else ""
) )
image_url = None image_url = None
idx = hit.meta.index idx = hit.meta.index
@ -121,32 +128,23 @@ def process_query(query: str = "", request: Request | None = None):
if idx == "products": if idx == "products":
prod = get_object_or_404(Product, uuid=obj_uuid) prod = get_object_or_404(Product, uuid=obj_uuid)
first = prod.images.order_by("priority").first() first = prod.images.order_by("priority").first()
image_url = ( if first and first.image:
request.build_absolute_uri(first.image.url) image_url = request.build_absolute_uri(first.image.url)
if first and first.image elif idx == "brands":
else None
)
if idx == "brands":
brand = get_object_or_404(Brand, uuid=obj_uuid) brand = get_object_or_404(Brand, uuid=obj_uuid)
image_url = ( if brand.small_logo:
request.build_absolute_uri(brand.small_logo.url) image_url = request.build_absolute_uri(brand.small_logo.url)
if brand.small_logo elif idx == "categories":
else None
)
if idx == "categories":
cat = get_object_or_404(Category, uuid=obj_uuid) cat = get_object_or_404(Category, uuid=obj_uuid)
image_url = ( if cat.image:
request.build_absolute_uri(cat.image.url) if cat.image else None image_url = request.build_absolute_uri(cat.image.url)
)
results[idx].append( results[idx].append({
{ "uuid": str(obj_uuid),
"uuid": str(obj_uuid), "name": obj_name,
"name": obj_name, "slug": obj_slug,
"slug": obj_slug, "image": image_url,
"image": image_url, })
}
)
return results return results