From e31c64eea82cb1cfd6ea70242668e4b519f881d0 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 19 Feb 2021 11:20:03 +0000 Subject: [PATCH] product search with ranking is working --- products/tests.py | 26 ++++++++++++++++++-------- products/utils.py | 10 +++------- products/views.py | 7 +++---- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/products/tests.py b/products/tests.py index 72c8aee..4f5ad49 100644 --- a/products/tests.py +++ b/products/tests.py @@ -467,8 +467,6 @@ class ProductSearchTest(TestCase): self.factory(tags="lunares/azules", description="zapatos rojos"), self.factory(tags="lunares/rojos", description="zapatos"), self.factory(attributes='"zapatos de campo", tono/oscuro'), - # TODO: workaround for v3 with multi-word tags - # self.factory(attributes='zapatos, "zapatos de campo", tono/oscuro'), ] unexpected_instances = [ self.factory(description="chanclas"), @@ -549,18 +547,29 @@ class FindRelatedProductsTest(APITestCase): # clear table self.model.objects.all().delete() - def test_v3_find_by_single_tag(self): + def test_v3_find_by_tags(self): # create tagged product tag = 'cool' expected_instances = [ - self.factory(tags=tag) + self.factory(tags=tag), + self.factory(tags=f'{tag} hat'), + self.factory(tags=f'temperatures/{tag}'), + self.factory(tags=f'temperatures/{tag}, body/hot'), + self.factory(tags=f'temperatures/{tag}, hats/{tag}'), + # multiple hits + self.factory(tags=tag, attributes=tag), + self.factory(tags=tag, attributes=tag, category=tag), + self.factory(tags=tag, attributes=tag, category=tag, name=tag), + self.factory(tags=tag, attributes=tag, category=tag, name=tag, description=tag), ] - # instance = self.factory() - # instance.tags.set(tag) - # instance.save() + + unexpected_instances = [ + self.factory(tags="notcool"), # shouldn't catch it + self.factory(tags="azules"), + ] + # searh for it results = find_related_products_v3(tag) - import ipdb; ipdb.set_trace() # assert result self.assertTrue(len(results) == len(expected_instances)) @@ -568,3 +577,4 @@ class FindRelatedProductsTest(APITestCase): + diff --git a/products/utils.py b/products/utils.py index 8353ef6..2b6f8e0 100644 --- a/products/utils.py +++ b/products/utils.py @@ -114,25 +114,21 @@ def find_related_products_v3(keyword): SearchVectors for the fields SearchQuery for the value SearchRank for relevancy scoring and ranking - - PROBLEM: returns unrelated instances """ - # TODO: figure out why it includes unrelated instances - # fields=('name', 'description', 'tags__label', 'attributes__label', 'category__name') - vector = SearchVector('name') + SearchVector('description') + SearchVector('tags__label') + SearchVector('attributes__label') + SearchVector('category__name') query = SearchQuery(keyword) products_qs = Product.objects.annotate( rank=SearchRank(vector, query) - ).filter(rank__gt=0.05).order_by('-rank') + ).filter(rank__gt=0.05) # removed order_by because its lost in casting return set(products_qs) def find_related_products_v4(keyword): """ - Using trigrams + Similarity-ranked search using trigrams + Not working """ # fields=('name', 'description', 'tags__label', 'attributes__label', 'category__name') diff --git a/products/views.py b/products/views.py index 44f8e6e..494c5f4 100644 --- a/products/views.py +++ b/products/views.py @@ -23,7 +23,7 @@ from companies.models import Company from history.models import HistorySync from back_latienda.permissions import IsCreator -from .utils import extract_search_filters, find_related_products_v5, find_related_products_v4, find_related_products_v3 +from .utils import extract_search_filters, find_related_products_v3 from utils.tag_serializers import TaggitSerializer from utils.tag_filters import ProductTagFilter @@ -155,9 +155,7 @@ def product_search(request): chunks = query_string.split(' ') for chunk in chunks: - product_set = find_related_products_v5(chunk) - # product_set = find_related_products_v4(chunk) - # product_set = find_related_products_v3(chunk) + product_set = find_related_products_v3(chunk) # add to result set result_set.update(product_set) # TODO: add search for entire phrase @@ -166,6 +164,7 @@ def product_search(request): filters = extract_search_filters(result_set) # serialize and respond product_serializer = ProductSearchSerializer(result_set, many=True, context={'request': request}) + # TODO: send product data in order by rank value return Response(data={"filters": filters, "products": product_serializer.data}) except Exception as e: return Response({"errors": {"details": str(e)}}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)