first steps for georestricted search results

This commit is contained in:
Sam
2021-03-11 11:11:00 +00:00
parent 391ada843c
commit 5178eb9722
2 changed files with 42 additions and 9 deletions

View File

@@ -7,6 +7,8 @@ from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
from django.db.models import Max, Min from django.db.models import Max, Min
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
import requests import requests
@@ -124,7 +126,7 @@ def get_related_products(product):
return total_results[:10] return total_results[:10]
def ranked_product_search(keyword, shipping_cost=None, discount=None, category=None, tags=None, price_min=None,price_max=None): def ranked_product_search(keyword, shipping_cost=None, discount=None, category=None, tags=None, price_min=None,price_max=None, coordinates=None):
""" """
Ranked product search Ranked product search
@@ -134,6 +136,12 @@ def ranked_product_search(keyword, shipping_cost=None, discount=None, category=N
allow filtering by: allow filtering by:
- shipping cost - shipping cost
Response includes:
- result_set
- min_price
- max_price
- georesult
""" """
vector = SearchVector('name') + SearchVector('description') + SearchVector('tags__label') + SearchVector('attributes__label') + SearchVector('category__label') + SearchVector('company__company_name') vector = SearchVector('name') + SearchVector('description') + SearchVector('tags__label') + SearchVector('attributes__label') + SearchVector('category__label') + SearchVector('company__company_name')
query = SearchQuery(keyword) query = SearchQuery(keyword)
@@ -142,6 +150,24 @@ def ranked_product_search(keyword, shipping_cost=None, discount=None, category=N
rank=SearchRank(vector, query) rank=SearchRank(vector, query)
).filter(rank__gt=0.05, active=True) ).filter(rank__gt=0.05, active=True)
# geolocation filtering
if coordinates is not None:
point = Point(coordinates)
filtered_qs = products_qs.filter(geo__distance_lte=(point, D(km=10)))
georesult = '10k'
if filtered_qs.count() <= 10:
products_qs = products_qs.filter(geo__distance_lte=(point, D(km=50)))
georesult = '50k'
if filtered_qs.count() <= 10:
products_qs = products_qs.filter(geo__distance_lte=(point, D(km=200)))
georesult = '200k'
if filtered_qs.count > 10:
products_qs = filtered_qs
else:
georesult = None
else:
georesult = None
# filter by category # filter by category
if category is not None: if category is not None:
products_qs = products_qs.filter(category=category) products_qs = products_qs.filter(category=category)
@@ -183,7 +209,7 @@ def ranked_product_search(keyword, shipping_cost=None, discount=None, category=N
max_price = products_qs.aggregate(Max('price')) max_price = products_qs.aggregate(Max('price'))
return set(products_qs), min_price, max_price return set(products_qs), min_price, max_price, georesult
def product_loader(csv_reader, user, company=None): def product_loader(csv_reader, user, company=None):

View File

@@ -19,6 +19,7 @@ from rest_framework.decorators import api_view, permission_classes, action
from rest_framework.filters import OrderingFilter from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
import requests import requests
from history.models import HistorySync from history.models import HistorySync
@@ -28,7 +29,7 @@ from products.models import Product, CategoryTag
from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer
from companies.models import Company from companies.models import Company
from stats.models import StatsLog from stats.models import StatsLog
from back_latienda.permissions import IsCreator, IsSiteAdmin, ReadOnly from back_latienda.permissions import IsCreator, IsSiteAdmin
from .utils import extract_search_filters, ranked_product_search, product_loader, get_related_products from .utils import extract_search_filters, ranked_product_search, product_loader, get_related_products
from utils.tag_serializers import TaggitSerializer from utils.tag_serializers import TaggitSerializer
from utils.tag_filters import ProductTagFilter, ProductOrderFilter from utils.tag_filters import ProductTagFilter, ProductOrderFilter
@@ -125,8 +126,8 @@ def product_search(request):
Params: Params:
- q: used for search [MANDATORY] - q: used for search [MANDATORY]
- limit: max number of returned instances [OPTIONAL] - limit: max number of returned instances
- offset: where to start counting results [OPTIONAL] - offset: where to start counting results
- shipping_cost: true/false - shipping_cost: true/false
- discount: true/false - discount: true/false
- category: string - category: string
@@ -134,6 +135,7 @@ def product_search(request):
- order: string (newest/oldest) - order: string (newest/oldest)
- price_min: int - price_min: int
- price_max: int - price_max: int
- geo: {'longitude': 23.23, 'latitude': 23432.23423}
In the response: In the response:
- filters - filters
@@ -163,6 +165,11 @@ def product_search(request):
discount = False discount = False
else: else:
discount = None discount = None
geo = request.GET.get('geo', None)
if geo is not None:
coordinates = (geo.get('longitude'), geo.get('latitude'))
else:
coordinates = None
category = request.GET.get('category', None) category = request.GET.get('category', None)
tags = request.GET.get('tags', None) tags = request.GET.get('tags', None)
price_min = request.GET.get('price_min', None) price_min = request.GET.get('price_min', None)
@@ -195,7 +202,7 @@ def product_search(request):
# 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 = ranked_product_search(chunk, shipping_cost, discount, category, tags, price_min, price_max) product_set, min_price, max_price, georesult = ranked_product_search(chunk, shipping_cost, discount, category, tags, price_min, price_max, coordinates)
# update price values # update price values
if product_set: if product_set:
if prices['min'] is None or min_price['price__min'] < prices['min']: if prices['min'] is None or min_price['price__min'] < prices['min']: