refactored the mechanism for finding similar establishments

This commit is contained in:
Anatoly 2019-12-12 18:10:20 +03:00
parent b58d54c07e
commit e2ec179f69
3 changed files with 70 additions and 16 deletions

View File

@ -213,7 +213,13 @@ class EstablishmentQuerySet(models.QuerySet):
))
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 = {
'reviews__status': Review.READY,
'establishment_type': establishment.establishment_type,
@ -224,27 +230,64 @@ class EstablishmentQuerySet(models.QuerySet):
.filter(**filters) \
.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):
"""
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,
public_mark__isnull=False)
restaurant_qs = self.filter(slug=slug)
if restaurant_qs.exists():
establishment = restaurant_qs.first()
subquery_filter_by_distance = Subquery(
self.similar_base(establishment)
.filter(public_mark__gte=10,
establishment_gallery__is_main=True)
.order_by('distance')[:settings.LIMITING_QUERY_OBJECTS]
.values('id')
restaurant = restaurant_qs.first()
ids_by_subquery = self.similar_base_subquery(
establishment=restaurant,
filters={
'public_mark__gte': 10,
'establishment_gallery__is_main': True,
}
)
return self.filter(id__in=subquery_filter_by_distance) \
return self.filter(id__in=ids_by_subquery) \
.annotate_intermediate_public_mark() \
.annotate_mark_similarity(mark=establishment.public_mark) \
.annotate_mark_similarity(mark=restaurant.public_mark) \
.order_by('mark_similarity') \
.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):
"""

View File

@ -21,6 +21,8 @@ urlpatterns = [
path('slug/<slug:slug>/similar/', views.RestaurantSimilarListView.as_view(),
name='similar-restaurants'),
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'),
]

View File

@ -87,7 +87,7 @@ class RestaurantSimilarListView(EstablishmentSimilarList):
"""Resource for getting a list of similar restaurants."""
def get_queryset(self):
"""Override get_queryset method"""
"""Overridden get_queryset method"""
return EstablishmentMixinView.get_queryset(self) \
.similar_restaurants(slug=self.kwargs.get('slug'))
@ -96,11 +96,20 @@ class WinerySimilarListView(EstablishmentSimilarList):
"""Resource for getting a list of similar wineries."""
def get_queryset(self):
"""Override get_queryset method"""
"""Overridden get_queryset method"""
return EstablishmentMixinView.get_queryset(self) \
.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):
"""Resource for getting a list of establishment types."""