mirror of
https://github.com/magnum-opus-tender-hack/backend.git
synced 2024-11-24 02:03:47 +03:00
added queried search
This commit is contained in:
parent
bbcf4bd2a7
commit
beab74a4f4
|
@ -60,6 +60,7 @@ DJANGO_APPS = [
|
|||
"django.contrib.humanize",
|
||||
"django.contrib.admin",
|
||||
"django.forms",
|
||||
"django.contrib.postgres",
|
||||
]
|
||||
THIRD_PARTY_APPS = ["rest_framework", "corsheaders", "drf_yasg"]
|
||||
|
||||
|
|
|
@ -2,9 +2,19 @@ from rest_framework import serializers
|
|||
from django.core.validators import MinLengthValidator, MinValueValidator
|
||||
|
||||
|
||||
class QueryFilterSerializer(serializers.Serializer):
|
||||
value = serializers.CharField(max_length=100)
|
||||
type = serializers.CharField(max_length=100)
|
||||
|
||||
def create(self, validated_data):
|
||||
raise NotImplementedError
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class SearchSerializer(serializers.Serializer):
|
||||
body = serializers.CharField(max_length=200)
|
||||
body = serializers.ListSerializer(child=QueryFilterSerializer())
|
||||
|
||||
def create(self, validated_data):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -5,47 +5,60 @@ from rest_framework.response import Response
|
|||
from rest_framework.views import APIView
|
||||
from search.api.serializers import HintRequestSerializer
|
||||
|
||||
from search.api.serializers import SearchSerializer, ResponseSerializer, HintResponseSerializer, AutoCompleteRequestSerializer, AutoCompleteResponseSerializer
|
||||
from search.services.search import process_string
|
||||
from search.api.serializers import (
|
||||
SearchSerializer,
|
||||
ResponseSerializer,
|
||||
HintResponseSerializer,
|
||||
AutoCompleteRequestSerializer,
|
||||
AutoCompleteResponseSerializer,
|
||||
)
|
||||
from search.services.search import process_search
|
||||
from search.services.autocomplete_schema import autocomplete_schema
|
||||
|
||||
from search.services.hints import get_hints
|
||||
|
||||
user_response = openapi.Response("search results", ResponseSerializer)
|
||||
hint_response = openapi.Response("hints", HintResponseSerializer)
|
||||
autocomplete_response = openapi.Response("autocomplete schema", AutoCompleteResponseSerializer)
|
||||
autocomplete_response = openapi.Response(
|
||||
"autocomplete schema", AutoCompleteResponseSerializer
|
||||
)
|
||||
|
||||
|
||||
class SearchApi(APIView):
|
||||
@swagger_auto_schema(request_body=SearchSerializer, responses={200: user_response})
|
||||
def post(self, request, format=None):
|
||||
def post(self, request):
|
||||
serializer = SearchSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return Response(
|
||||
process_string(serializer.data["body"]), status=status.HTTP_200_OK
|
||||
process_search(serializer.data["body"]), status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
|
||||
class HintApi(APIView):
|
||||
@swagger_auto_schema(request_body=HintRequestSerializer, responses={200: hint_response})
|
||||
def post(self, request, format=None):
|
||||
@swagger_auto_schema(
|
||||
request_body=HintRequestSerializer, responses={200: hint_response}
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = HintRequestSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return Response(
|
||||
{
|
||||
'type': get_hints(serializer.data['content']),
|
||||
'value': serializer.data['content']
|
||||
"type": get_hints(serializer.data["content"]),
|
||||
"value": serializer.data["content"],
|
||||
},
|
||||
status=status.HTTP_200_OK
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class AutoCompleteApi(APIView):
|
||||
@swagger_auto_schema(request_body=AutoCompleteRequestSerializer, responses={200: autocomplete_response})
|
||||
def post(self, request, format=None):
|
||||
@swagger_auto_schema(
|
||||
request_body=AutoCompleteRequestSerializer,
|
||||
responses={200: autocomplete_response},
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = AutoCompleteRequestSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return Response(
|
||||
{
|
||||
'nodes': autocomplete_schema(serializer.data['content'])
|
||||
}, status=status.HTTP_200_OK
|
||||
{"nodes": autocomplete_schema(serializer.data["content"])},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
|
|
@ -49,6 +49,8 @@ class Product(models.Model):
|
|||
Category, related_name="products", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
# score = models.IntegerField(default=0)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name)
|
||||
|
||||
|
@ -56,13 +58,17 @@ class Product(models.Model):
|
|||
return {
|
||||
"name": self.name,
|
||||
"characteristic": [
|
||||
x.serialize_self() for x in self.characteristics.objects.all()
|
||||
x.characteristic.serialize_self() for x in self.characteristics.all()
|
||||
]
|
||||
+ [x.serialize_self() for x in self.unit_characteristics.objects.all()],
|
||||
+ [
|
||||
x.characteristic.serialize_self()
|
||||
for x in self.unit_characteristics.all()
|
||||
],
|
||||
}
|
||||
|
||||
class Meta:
|
||||
db_table = "product"
|
||||
# ordering = ["score"]
|
||||
|
||||
|
||||
class ProductCharacteristic(models.Model):
|
||||
|
|
|
@ -1,37 +1,38 @@
|
|||
from search.models import Product, Category, Characteristic
|
||||
|
||||
|
||||
def autocomplete_schema(val: str):
|
||||
schema = []
|
||||
schema.extend(
|
||||
[
|
||||
{
|
||||
'coordinate': product['name'].index(val),
|
||||
'value': {
|
||||
'type': 'Name',
|
||||
'value': product['name'],
|
||||
"coordinate": product["name"].index(val),
|
||||
"value": {
|
||||
"type": "Name",
|
||||
"value": product["name"],
|
||||
},
|
||||
}
|
||||
} for product in Product.objects.filter(name__contains=val).values('name')]
|
||||
)
|
||||
schema.extend(
|
||||
[
|
||||
{
|
||||
'coordinate': cat['name'].index(val),
|
||||
'value': {
|
||||
'type': 'Category',
|
||||
'value': cat['name']
|
||||
}
|
||||
} for cat in Category.objects.filter(name__contains=val).values('name')
|
||||
for product in Product.objects.filter(name__contains=val).values("name")
|
||||
]
|
||||
)
|
||||
schema.extend(
|
||||
[
|
||||
{
|
||||
'coordinate': char.name.index(val),
|
||||
'value': {
|
||||
'type': char.name,
|
||||
'value': char.value
|
||||
"coordinate": cat["name"].index(val),
|
||||
"value": {"type": "Category", "value": cat["name"]},
|
||||
}
|
||||
} for char in Characteristic.objects.filter(name__contains=val).values('name', 'value')
|
||||
for cat in Category.objects.filter(name__contains=val).values("name")
|
||||
]
|
||||
)
|
||||
schema.extend(
|
||||
[
|
||||
{
|
||||
"coordinate": char.name.index(val),
|
||||
"value": {"type": char.name, "value": char.value},
|
||||
}
|
||||
for char in Characteristic.objects.filter(name__contains=val).values(
|
||||
"name", "value"
|
||||
)
|
||||
]
|
||||
)
|
||||
return schema
|
||||
|
|
|
@ -2,11 +2,11 @@ from search.models import Product, Category, Characteristic
|
|||
|
||||
|
||||
def get_hints(content: str) -> str:
|
||||
category = 'Unknown'
|
||||
category = "Unknown"
|
||||
if content in list(map(lambda product: product.name, Product.objects.all())):
|
||||
category = 'Name'
|
||||
category = "Name"
|
||||
elif content in list(map(lambda category: category.name, Category.objects.all())):
|
||||
category = 'Category'
|
||||
category = "Category"
|
||||
elif content in list(map(lambda char: char.value, Characteristic.objects.all())):
|
||||
category = Characteristic.objects.get(value=content).name
|
||||
return category
|
||||
|
|
|
@ -1,6 +1,44 @@
|
|||
from search.models import Product
|
||||
from search.models import Product, Characteristic, ProductCharacteristic
|
||||
from typing import List
|
||||
|
||||
|
||||
def process_string(text: str) -> List[dict]:
|
||||
return [x.serialize_self() for x in Product.objects.filter(name__contains=text)[5:]]
|
||||
def process_search(data: List[dict]) -> List[dict]:
|
||||
prep_data = []
|
||||
prep_dict = {}
|
||||
prep_dict_char_type = {}
|
||||
|
||||
for x in data:
|
||||
dat = dict(x)
|
||||
if x["type"] in ["Name", "Category", "Unknown"]:
|
||||
prep_data.append(dat)
|
||||
else:
|
||||
if x["type"] in list(prep_dict.keys()):
|
||||
prep_dict[x["type"]] = prep_dict[
|
||||
x["type"]
|
||||
] | ProductCharacteristic.objects.filter(
|
||||
characteristic__in=prep_dict_char_type[x["type"]],
|
||||
characteristic__value__unaccent__trigram_similar=x["value"],
|
||||
)
|
||||
else:
|
||||
prep_dict_char_type[x["type"]] = Characteristic.objects.filter(
|
||||
name__contains=x["type"]
|
||||
)
|
||||
prep_dict[x["type"]] = ProductCharacteristic.objects.filter(
|
||||
characteristic__in=prep_dict_char_type[x["type"]],
|
||||
characteristic__value__unaccent__trigram_similar=x["value"],
|
||||
)
|
||||
for el, val in prep_dict.items():
|
||||
prep_data.append({"type": el, "value": val})
|
||||
qs = Product.objects.filter()
|
||||
for x in prep_data:
|
||||
typ = x["type"]
|
||||
val = x["value"]
|
||||
if typ == "Name":
|
||||
qs = qs.filter(name__unaccent__trigram_similar=val)
|
||||
elif typ == "Category":
|
||||
qs = qs.filter(category__name__unaccent__trigram_similar=val)
|
||||
elif typ == "Unknown":
|
||||
continue
|
||||
else:
|
||||
qs = qs.filter(characteristics__in=val)
|
||||
return [x.serialize_self() for x in qs[:5]]
|
||||
|
|
Loading…
Reference in New Issue
Block a user