partial improvements to search
This commit is contained in:
@@ -535,6 +535,37 @@ class ProductSearchTest(TestCase):
|
|||||||
# check prices
|
# check prices
|
||||||
self.assertTrue(payload['prices']['min'] <= payload['prices']['max'])
|
self.assertTrue(payload['prices']['min'] <= payload['prices']['max'])
|
||||||
|
|
||||||
|
def test_anon_user_can_search_no_querystring(self):
|
||||||
|
expected_instances = [
|
||||||
|
self.factory(tags="lunares/rojos", category='zapatos', description="zapatos verdes"),
|
||||||
|
self.factory(tags="colores/rojos, tono/brillante"),
|
||||||
|
self.factory(tags="lunares/azules", description="zapatos rojos"),
|
||||||
|
self.factory(tags="lunares/rojos", description="zapatos"),
|
||||||
|
self.factory(attributes='"zapatos de campo", tono/oscuro'),
|
||||||
|
]
|
||||||
|
unexpected_instances = [
|
||||||
|
self.factory(description="chanclas"),
|
||||||
|
self.factory(tags="azules"),
|
||||||
|
]
|
||||||
|
|
||||||
|
q = quote("zapatos rojos")
|
||||||
|
|
||||||
|
url = f"{self.endpoint}?q="
|
||||||
|
# send in request
|
||||||
|
response = self.client.get(url)
|
||||||
|
# check response
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# load response data
|
||||||
|
payload = response.json()
|
||||||
|
# check for expected fields in payload
|
||||||
|
self.assertIsNotNone(payload.get('filters'))
|
||||||
|
self.assertIsNotNone(payload.get('count'))
|
||||||
|
self.assertIsNotNone(payload.get('products'))
|
||||||
|
self.assertIsNotNone(payload.get('prices'))
|
||||||
|
|
||||||
|
# check for object creation
|
||||||
|
self.assertEquals(len(payload['products']), len(expected_instances) + len(unexpected_instances))
|
||||||
|
|
||||||
def test_anon_user_can_paginate_search(self):
|
def test_anon_user_can_paginate_search(self):
|
||||||
expected_instances = [
|
expected_instances = [
|
||||||
self.factory(tags="lunares/rojos", category='zapatos', description="zapatos verdes"),
|
self.factory(tags="lunares/rojos", category='zapatos', description="zapatos verdes"),
|
||||||
@@ -549,10 +580,10 @@ class ProductSearchTest(TestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
q = quote("zapatos rojos")
|
q = quote("zapatos rojos")
|
||||||
limit = 2
|
|
||||||
|
|
||||||
|
# test limit less than available
|
||||||
|
limit = 3
|
||||||
url = f"{self.endpoint}?q={q}&limit={limit}"
|
url = f"{self.endpoint}?q={q}&limit={limit}"
|
||||||
# send in request
|
|
||||||
response = self.client.get(url)
|
response = self.client.get(url)
|
||||||
|
|
||||||
# check response
|
# check response
|
||||||
@@ -562,6 +593,44 @@ class ProductSearchTest(TestCase):
|
|||||||
self.assertEquals(len(payload['products']), limit)
|
self.assertEquals(len(payload['products']), limit)
|
||||||
self.assertEquals(payload['count'], len(expected_instances))
|
self.assertEquals(payload['count'], len(expected_instances))
|
||||||
|
|
||||||
|
# test limit less than available
|
||||||
|
limit = 10
|
||||||
|
url = f"{self.endpoint}?q={q}&limit={limit}"
|
||||||
|
response = self.client.get(url)
|
||||||
|
|
||||||
|
# check response
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# load response data
|
||||||
|
payload = response.json()
|
||||||
|
self.assertEquals(len(payload['products']), len(expected_instances))
|
||||||
|
self.assertEquals(payload['count'], len(expected_instances))
|
||||||
|
|
||||||
|
# test limit equal to available, offset zero
|
||||||
|
limit = len(expected_instances)
|
||||||
|
offset = 0
|
||||||
|
url = f"{self.endpoint}?q={q}&limit={limit}&offset={offset}"
|
||||||
|
response = self.client.get(url)
|
||||||
|
|
||||||
|
# check response
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# load response data
|
||||||
|
payload = response.json()
|
||||||
|
self.assertEquals(len(payload['products']), len(expected_instances))
|
||||||
|
self.assertEquals(payload['count'], len(expected_instances))
|
||||||
|
|
||||||
|
# test limit and offset equal to available
|
||||||
|
limit = len(expected_instances)
|
||||||
|
offset = limit
|
||||||
|
url = f"{self.endpoint}?q={q}&limit={limit}&offset={offset}"
|
||||||
|
response = self.client.get(url)
|
||||||
|
|
||||||
|
# check response
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# load response data
|
||||||
|
payload = response.json()
|
||||||
|
self.assertEquals(len(payload['products']), 0)
|
||||||
|
self.assertEquals(payload['count'], len(expected_instances))
|
||||||
|
|
||||||
def test_anon_user_can_filter_shipping_cost_true(self):
|
def test_anon_user_can_filter_shipping_cost_true(self):
|
||||||
expected_instances = [
|
expected_instances = [
|
||||||
self.factory(tags="colores/rojos, tono/brillante", shipping_cost=100.00),
|
self.factory(tags="colores/rojos, tono/brillante", shipping_cost=100.00),
|
||||||
@@ -685,7 +754,6 @@ class ProductSearchTest(TestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
q = quote("zapatos rojos")
|
q = quote("zapatos rojos")
|
||||||
# discount=true
|
|
||||||
url = f"{self.endpoint}?q={q}&category=ropa/nueva"
|
url = f"{self.endpoint}?q={q}&category=ropa/nueva"
|
||||||
# send in request
|
# send in request
|
||||||
response = self.client.get(url)
|
response = self.client.get(url)
|
||||||
@@ -815,7 +883,7 @@ class ProductSearchTest(TestCase):
|
|||||||
url = f"{self.endpoint}?q={q}&order=oldest"
|
url = f"{self.endpoint}?q={q}&order=oldest"
|
||||||
# send in request
|
# send in request
|
||||||
response = self.client.get(url)
|
response = self.client.get(url)
|
||||||
|
import ipdb; ipdb.set_trace()
|
||||||
# check response
|
# check response
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
# load response data
|
# load response data
|
||||||
|
|||||||
@@ -141,12 +141,7 @@ def product_search(request):
|
|||||||
|
|
||||||
if q is None:
|
if q is None:
|
||||||
return Response({"errors": {"details": "No query string to parse"}})
|
return Response({"errors": {"details": "No query string to parse"}})
|
||||||
elif q is '':
|
|
||||||
# return everything
|
|
||||||
serializer = ProductSerializer(Product.objects.all(), many=True)
|
|
||||||
products = serializer.data
|
|
||||||
# filters = extract_search_filters(products)
|
|
||||||
return Response(data={"filters": [], "count": len(products), "products": products})
|
|
||||||
try:
|
try:
|
||||||
# we collect our results here
|
# we collect our results here
|
||||||
result_set = set()
|
result_set = set()
|
||||||
@@ -156,49 +151,55 @@ def product_search(request):
|
|||||||
'max': None,
|
'max': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if q == '':
|
||||||
|
# filter entire queryset
|
||||||
|
products_qs = Product.objects.all()
|
||||||
|
if tags:
|
||||||
|
products_qs = Product.objects.filter(tags=tags)
|
||||||
|
if category:
|
||||||
|
products_qs = Product.objects.filter(category=category)
|
||||||
|
# serialize and list data
|
||||||
|
serializer = ProductSerializer(products_qs, many=True)
|
||||||
|
result_list = [dict(i) for i in serializer.data]
|
||||||
|
else:
|
||||||
# split query string into single words
|
# split query string into single words
|
||||||
chunks = q.split(' ')
|
chunks = q.split(' ')
|
||||||
for chunk in chunks:
|
for chunk in chunks:
|
||||||
product_set, min_price, max_price = find_related_products_v6(chunk, shipping_cost, discount, category, tags, price_min, price_max)
|
product_set, min_price, max_price = find_related_products_v6(chunk, shipping_cost, discount, category, tags, price_min, price_max)
|
||||||
# update price values
|
# update price values
|
||||||
if product_set:
|
if product_set:
|
||||||
# import ipdb; ipdb.set_trace()
|
|
||||||
if prices['min'] is None or min_price['price__min'] < prices['min']:
|
if prices['min'] is None or min_price['price__min'] < prices['min']:
|
||||||
prices['min'] = min_price['price__min']
|
prices['min'] = min_price['price__min']
|
||||||
if prices['max'] is None or max_price['price__max'] > prices['max']:
|
if prices['max'] is None or max_price['price__max'] > prices['max']:
|
||||||
prices['max'] = max_price['price__max']
|
prices['max'] = max_price['price__max']
|
||||||
# add to result set
|
# add to result set
|
||||||
result_set.update(product_set)
|
result_set.update(product_set)
|
||||||
# TODO: add search for entire phrase ???
|
# serialize and list data
|
||||||
|
serializer = SearchResultSerializer(product_set, many=True)
|
||||||
|
result_list = [dict(i) for i in serializer.data]
|
||||||
|
|
||||||
# extract filters from result_set
|
# extract filters from result_set
|
||||||
filters = extract_search_filters(result_set)
|
filters = extract_search_filters(result_set)
|
||||||
|
# order the results
|
||||||
result_list = list(result_set)
|
|
||||||
if order == 'newest':
|
if order == 'newest':
|
||||||
# order results by created
|
# order results by created
|
||||||
ordered_products = sorted(result_list, key= lambda x:x.created, reverse=True)
|
result_list = sorted(result_list, key= lambda x:x['created'], reverse=True)
|
||||||
elif order == 'oldest':
|
elif order == 'oldest':
|
||||||
# order results by created
|
# order results by created
|
||||||
ordered_products = sorted(result_list, key= lambda x:x.created, reverse=False)
|
result_list = sorted(result_list, key= lambda x:x['created'], reverse=False)
|
||||||
else:
|
elif q != '':
|
||||||
# order results by RANK
|
# order results by RANK
|
||||||
ordered_products = sorted(result_list, key= lambda rank:rank.rank, reverse=True)
|
result_list = sorted(result_list, key= lambda x:x['rank'], reverse=True)
|
||||||
|
|
||||||
# extract max and min price values
|
|
||||||
serializer = SearchResultSerializer(ordered_products, many=True)
|
|
||||||
product_results = [dict(i) for i in serializer.data]
|
|
||||||
total_results = len(product_results)
|
|
||||||
|
|
||||||
|
total_results = len(result_list)
|
||||||
# RESULTS PAGINATION
|
# RESULTS PAGINATION
|
||||||
if limit is not None and offset is not None:
|
if limit is not None and offset is not None:
|
||||||
limit = int(limit)
|
limit = int(limit)
|
||||||
offset = int(offset)
|
offset = int(offset)
|
||||||
product_results = product_results[offset:(limit+offset)]
|
result_list = result_list[offset:(limit+offset)]
|
||||||
elif limit is not None:
|
elif limit is not None:
|
||||||
limit = int(limit)
|
limit = int(limit)
|
||||||
product_results = product_results[:limit]
|
result_list = result_list[:limit]
|
||||||
|
return Response(data={"filters": filters, "count": total_results, "products": result_list, 'prices': prices})
|
||||||
return Response(data={"filters": filters, "count": total_results, "products": product_results, 'prices': prices})
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Response({"errors": {"details": str(e)}}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
return Response({"errors": {"details": str(e)}}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
|
|||||||
Reference in New Issue
Block a user