refactored the mechanism for finding similar establishments
This commit is contained in:
parent
b58d54c07e
commit
e2ec179f69
|
|
@ -213,7 +213,13 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
))
|
))
|
||||||
|
|
||||||
def similar_base(self, establishment):
|
def similar_base(self, establishment):
|
||||||
|
"""
|
||||||
|
Return filtered QuerySet by base filters.
|
||||||
|
Filters including:
|
||||||
|
1 Filter by type (and subtype) establishment.
|
||||||
|
2 Filter by published Review.
|
||||||
|
3 With annotated distance.
|
||||||
|
"""
|
||||||
filters = {
|
filters = {
|
||||||
'reviews__status': Review.READY,
|
'reviews__status': Review.READY,
|
||||||
'establishment_type': establishment.establishment_type,
|
'establishment_type': establishment.establishment_type,
|
||||||
|
|
@ -224,27 +230,64 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
.filter(**filters) \
|
.filter(**filters) \
|
||||||
.annotate_distance(point=establishment.location)
|
.annotate_distance(point=establishment.location)
|
||||||
|
|
||||||
|
def similar_base_subquery(self, establishment, filters: dict) -> Subquery:
|
||||||
|
"""
|
||||||
|
Return filtered Subquery object by filters.
|
||||||
|
Filters including:
|
||||||
|
1 Filter by transmitted filters.
|
||||||
|
2 With ordering by distance.
|
||||||
|
"""
|
||||||
|
return Subquery(
|
||||||
|
self.similar_base(establishment)
|
||||||
|
.filter(**filters)
|
||||||
|
.order_by('distance')[:settings.LIMITING_QUERY_OBJECTS]
|
||||||
|
.values('id')
|
||||||
|
)
|
||||||
|
|
||||||
def similar_restaurants(self, slug):
|
def similar_restaurants(self, slug):
|
||||||
"""
|
"""
|
||||||
Return QuerySet with objects that similar to Restaurant.
|
Return QuerySet with objects that similar to Restaurant.
|
||||||
:param restaurant_slug: str Establishment slug
|
:param slug: str restaurant slug
|
||||||
"""
|
"""
|
||||||
restaurant_qs = self.filter(slug=slug,
|
restaurant_qs = self.filter(slug=slug)
|
||||||
public_mark__isnull=False)
|
|
||||||
if restaurant_qs.exists():
|
if restaurant_qs.exists():
|
||||||
establishment = restaurant_qs.first()
|
restaurant = restaurant_qs.first()
|
||||||
subquery_filter_by_distance = Subquery(
|
ids_by_subquery = self.similar_base_subquery(
|
||||||
self.similar_base(establishment)
|
establishment=restaurant,
|
||||||
.filter(public_mark__gte=10,
|
filters={
|
||||||
establishment_gallery__is_main=True)
|
'public_mark__gte': 10,
|
||||||
.order_by('distance')[:settings.LIMITING_QUERY_OBJECTS]
|
'establishment_gallery__is_main': True,
|
||||||
.values('id')
|
}
|
||||||
)
|
)
|
||||||
return self.filter(id__in=subquery_filter_by_distance) \
|
return self.filter(id__in=ids_by_subquery) \
|
||||||
.annotate_intermediate_public_mark() \
|
.annotate_intermediate_public_mark() \
|
||||||
.annotate_mark_similarity(mark=establishment.public_mark) \
|
.annotate_mark_similarity(mark=restaurant.public_mark) \
|
||||||
.order_by('mark_similarity') \
|
.order_by('mark_similarity') \
|
||||||
.distinct('mark_similarity', 'id')
|
.distinct('mark_similarity', 'id')
|
||||||
|
else:
|
||||||
|
return self.none()
|
||||||
|
|
||||||
|
def similar_artisans(self, slug):
|
||||||
|
"""
|
||||||
|
Return QuerySet with objects that similar to Artisan.
|
||||||
|
:param slug: str artisan slug
|
||||||
|
"""
|
||||||
|
artisan_qs = self.filter(slug=slug)
|
||||||
|
if artisan_qs.exists():
|
||||||
|
artisan = artisan_qs.first()
|
||||||
|
ids_by_subquery = self.similar_base_subquery(
|
||||||
|
establishment=artisan,
|
||||||
|
filters={
|
||||||
|
'public_mark__gte': 10,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return self.filter(id__in=ids_by_subquery) \
|
||||||
|
.annotate_intermediate_public_mark() \
|
||||||
|
.annotate_mark_similarity(mark=artisan.public_mark) \
|
||||||
|
.order_by('mark_similarity') \
|
||||||
|
.distinct('mark_similarity', 'id')
|
||||||
|
else:
|
||||||
|
return self.none()
|
||||||
|
|
||||||
def by_wine_region(self, wine_region):
|
def by_wine_region(self, wine_region):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ urlpatterns = [
|
||||||
path('slug/<slug:slug>/similar/', views.RestaurantSimilarListView.as_view(),
|
path('slug/<slug:slug>/similar/', views.RestaurantSimilarListView.as_view(),
|
||||||
name='similar-restaurants'),
|
name='similar-restaurants'),
|
||||||
path('slug/<slug:slug>/similar/wineries/', views.WinerySimilarListView.as_view(),
|
path('slug/<slug:slug>/similar/wineries/', views.WinerySimilarListView.as_view(),
|
||||||
name='similar-restaurants'),
|
name='similar-wineries'),
|
||||||
|
path('slug/<slug:slug>/similar/artisans/', views.ArtisanSimilarListView.as_view(),
|
||||||
|
name='similar-artisans'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ class RestaurantSimilarListView(EstablishmentSimilarList):
|
||||||
"""Resource for getting a list of similar restaurants."""
|
"""Resource for getting a list of similar restaurants."""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Override get_queryset method"""
|
"""Overridden get_queryset method"""
|
||||||
return EstablishmentMixinView.get_queryset(self) \
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
.similar_restaurants(slug=self.kwargs.get('slug'))
|
.similar_restaurants(slug=self.kwargs.get('slug'))
|
||||||
|
|
||||||
|
|
@ -96,11 +96,20 @@ class WinerySimilarListView(EstablishmentSimilarList):
|
||||||
"""Resource for getting a list of similar wineries."""
|
"""Resource for getting a list of similar wineries."""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Override get_queryset method"""
|
"""Overridden get_queryset method"""
|
||||||
return EstablishmentMixinView.get_queryset(self) \
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
.similar_wineries(slug=self.kwargs.get('slug'))
|
.similar_wineries(slug=self.kwargs.get('slug'))
|
||||||
|
|
||||||
|
|
||||||
|
class ArtisanSimilarListView(EstablishmentSimilarList):
|
||||||
|
"""Resource for getting a list of similar artisans."""
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Overridden get_queryset method"""
|
||||||
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
|
.similar_artisans(slug=self.kwargs.get('slug'))
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentTypeListView(generics.ListAPIView):
|
class EstablishmentTypeListView(generics.ListAPIView):
|
||||||
"""Resource for getting a list of establishment types."""
|
"""Resource for getting a list of establishment types."""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user