mirror of
https://github.com/magnum-opus-tender-hack/backend.git
synced 2025-02-18 10:20:32 +03:00
made all search smart
This commit is contained in:
parent
f823bcff62
commit
a47a89a43f
|
@ -8,37 +8,37 @@ def autocomplete_schema(val: str, exclude: List[Dict]):
|
||||||
name_exclude = [x["value"] for x in exclude if x["type"] == "Name"]
|
name_exclude = [x["value"] for x in exclude if x["type"] == "Name"]
|
||||||
category_exclude = [x["value"] for x in exclude if x["type"] == "Category"]
|
category_exclude = [x["value"] for x in exclude if x["type"] == "Category"]
|
||||||
schema = []
|
schema = []
|
||||||
|
if not category_exclude:
|
||||||
|
schema.extend(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"coordinate": cat["name"].replace("ё", "е").lower().index(val.lower()),
|
||||||
|
"value": {"type": "Category", "value": cat["name"]},
|
||||||
|
}
|
||||||
|
for cat in Category.objects.filter(name__unaccent__icontains=val)[
|
||||||
|
:10
|
||||||
|
].values("name")
|
||||||
|
]
|
||||||
|
)
|
||||||
if not name_exclude:
|
if not name_exclude:
|
||||||
schema.extend(
|
schema.extend(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"coordinate": product["name"].lower().index(val.lower()),
|
"coordinate": product["name"].replace("ё", "е").lower().index(val.lower()),
|
||||||
"value": {
|
"value": {
|
||||||
"type": "Name",
|
"type": "Name",
|
||||||
"value": product["name"],
|
"value": product["name"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for product in Product.objects.filter(name__unaccent__icontains=val)[
|
for product in Product.objects.filter(name__unaccent__icontains=val)[
|
||||||
:20
|
:30
|
||||||
].values("name")
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if not category_exclude:
|
|
||||||
schema.extend(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"coordinate": cat["name"].lower().index(val.lower()),
|
|
||||||
"value": {"type": "Category", "value": cat["name"]},
|
|
||||||
}
|
|
||||||
for cat in Category.objects.filter(name__unaccent__icontains=val)[
|
|
||||||
:20
|
|
||||||
].values("name")
|
].values("name")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
schema.extend(
|
schema.extend(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"coordinate": char["value"].lower().index(val.lower()),
|
"coordinate": char["value"].replace("ё", "е").lower().index(val.lower()),
|
||||||
"value": {"type": char["name"], "value": char["value"]},
|
"value": {"type": char["name"], "value": char["value"]},
|
||||||
}
|
}
|
||||||
for char in Characteristic.objects.filter(value__unaccent__icontains=val)[
|
for char in Characteristic.objects.filter(value__unaccent__icontains=val)[
|
||||||
|
@ -49,12 +49,12 @@ def autocomplete_schema(val: str, exclude: List[Dict]):
|
||||||
schema.extend(
|
schema.extend(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"coordinate": char["value"].lower().index(val.lower()),
|
"coordinate": char["name"].lower().replace("ё", "е").index(val.lower()),
|
||||||
"value": {
|
"value": {
|
||||||
"type": char["name"] + "_numeric",
|
"type": char["name"] + "_numeric",
|
||||||
"value": char["value"]
|
"value": char["name"]
|
||||||
}
|
}
|
||||||
} for char in UnitCharacteristic.objects.filter(value__unaccent__icontains=val)[:20].values("name", "value")
|
} for char in UnitCharacteristic.objects.filter(name__unaccent__icontains=val)[:20].values("name", "value")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return schema
|
return schema
|
||||||
|
|
|
@ -18,7 +18,7 @@ def group(data: List[Dict], search_fields_d: List[Dict]) -> List[Dict]:
|
||||||
else:
|
else:
|
||||||
re[field] = []
|
re[field] = []
|
||||||
re[field].append(
|
re[field].append(
|
||||||
[x["type"] for x in search_fields_dict if x["value"] == field][
|
[x["type"] for x in search_fields_dict if x["value"].lower() == field][
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,7 +43,7 @@ def _clean_text(text: str) -> List[str]:
|
||||||
text = text.split()
|
text = text.split()
|
||||||
re = []
|
re = []
|
||||||
for word in text:
|
for word in text:
|
||||||
re.append(lemmatize(word))
|
re.append(word)
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,35 +62,76 @@ def apply_qs_search(text: str):
|
||||||
|
|
||||||
def apply_all_qs_search(orig_qs, text: str):
|
def apply_all_qs_search(orig_qs, text: str):
|
||||||
# words
|
# words
|
||||||
qs = apply_qs_search(text)
|
|
||||||
text = _clean_text(text)
|
text = _clean_text(text)
|
||||||
|
|
||||||
# categories
|
u_qs = None
|
||||||
cats = Category.objects.none()
|
|
||||||
for word in text:
|
|
||||||
cats = cats | cats.filter(name__icontains=word)
|
|
||||||
qs = Product.objects.filter(category__in=cats).order_by("-score") | qs
|
|
||||||
|
|
||||||
# characteristics
|
# try to find Unit characteristics
|
||||||
chars = Characteristic.objects.none()
|
if any(x.isnumeric() for x in text):
|
||||||
|
u_qs = ProductUnitCharacteristic.objects.filter()
|
||||||
|
for i in range(len(text)):
|
||||||
|
el = text[i]
|
||||||
|
if el.isnumeric():
|
||||||
|
if i == len(text) - 1:
|
||||||
|
if ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i - 1]
|
||||||
|
).exists():
|
||||||
|
unit = ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i - 1]
|
||||||
|
)
|
||||||
|
u_qs = u_qs & process_unit_operation(unit, f"={text[i]}")
|
||||||
|
del text[i]
|
||||||
|
del text[i - 1]
|
||||||
|
break
|
||||||
|
elif len(text) - 1 > i >= 1:
|
||||||
|
if ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i - 1]
|
||||||
|
).exists():
|
||||||
|
unit = ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i - 1]
|
||||||
|
)[0]
|
||||||
|
u_qs = u_qs & process_unit_operation(unit, f"={text[i]}")
|
||||||
|
del text[i]
|
||||||
|
del text[i - 1]
|
||||||
|
break
|
||||||
|
elif ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i + 1]
|
||||||
|
).exists():
|
||||||
|
unit = UnitCharacteristic.objects.filter(
|
||||||
|
ProductUnitCharacteristic=text[i + 1]
|
||||||
|
)[0]
|
||||||
|
u_qs = u_qs & process_unit_operation(unit, f"={text[i]}")
|
||||||
|
del text[i]
|
||||||
|
del text[i + 1]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i + 1]
|
||||||
|
).exists():
|
||||||
|
unit = ProductUnitCharacteristic.objects.filter(
|
||||||
|
characteristic__name__icontains=text[i + 1]
|
||||||
|
)[0]
|
||||||
|
u_qs = u_qs & process_unit_operation(unit, f"={text[i]}")
|
||||||
|
del text[i]
|
||||||
|
del text[i + 1]
|
||||||
|
break
|
||||||
|
|
||||||
|
prod = Product.objects.filter()
|
||||||
for word in text:
|
for word in text:
|
||||||
chars = (
|
car = ProductCharacteristic.objects.filter(
|
||||||
chars
|
characteristic__value__icontains=word,
|
||||||
| Characteristic.objects.filter(
|
|
||||||
value__icontains=word,
|
|
||||||
)
|
|
||||||
| Characteristic.objects.filter(
|
|
||||||
value__unaccent__trigram_similar=word,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
qs = (
|
qs = (
|
||||||
Product.objects.filter(characteristics__characteristic__in=chars).order_by(
|
Product.objects.filter(name__icontains=word)
|
||||||
"-score"
|
| Product.objects.filter(name__unaccent__trigram_similar=word)
|
||||||
)
|
| Product.objects.filter(category__name__icontains=word)
|
||||||
| qs
|
| Product.objects.filter(characteristics__in=car)
|
||||||
)
|
)
|
||||||
|
prod = prod & qs
|
||||||
|
if u_qs:
|
||||||
|
prod = prod & Product.objects.filter(unit_characteristics__in=u_qs)
|
||||||
|
|
||||||
return qs & orig_qs
|
return prod
|
||||||
|
|
||||||
|
|
||||||
def process_search(data: List[dict], limit=5, offset=0) -> List[dict]:
|
def process_search(data: List[dict], limit=5, offset=0) -> List[dict]:
|
||||||
|
@ -174,11 +215,9 @@ def process_search(data: List[dict], limit=5, offset=0) -> List[dict]:
|
||||||
qs = qs & apply_qs_search(val)
|
qs = qs & apply_qs_search(val)
|
||||||
qs = qs.order_by("-score")
|
qs = qs.order_by("-score")
|
||||||
elif typ == "All":
|
elif typ == "All":
|
||||||
qs = apply_all_qs_search(qs, val)
|
qs = apply_all_qs_search(qs, val) & qs
|
||||||
elif typ == "Category":
|
elif typ == "Category":
|
||||||
qs = qs.filter(category__name__unaccent__trigram_similar=val) | qs.filter(
|
qs = qs.filter(category__name__icontains=val)
|
||||||
category__name__icontains=val
|
|
||||||
)
|
|
||||||
qs = qs.order_by("-score")
|
qs = qs.order_by("-score")
|
||||||
elif typ == "Characteristic":
|
elif typ == "Characteristic":
|
||||||
char = ProductCharacteristic.objects.filter(product__in=qs)
|
char = ProductCharacteristic.objects.filter(product__in=qs)
|
||||||
|
|
|
@ -19,6 +19,9 @@ def spell_check_en(word: str) -> str:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
morph = pymorphy2.MorphAnalyzer()
|
||||||
|
|
||||||
|
|
||||||
def lemmatize(word):
|
def lemmatize(word):
|
||||||
p = pymorphy2.MorphAnalyzer().parse(word)[0]
|
p = morph.parse(word)[0]
|
||||||
return p.normal_form
|
return p.normal_form
|
||||||
|
|
Loading…
Reference in New Issue
Block a user