Django Weighted Query (annotated Values)
I am attempting to created a query and sort it based on a custom calculation of weights. I require some help as the solution I have come to does indeed work but the performance is
Solution 1:
First, you would need to make sure that division would yield floats (without rounding). You would need something like this (disgracefully stolen here):
ExpressionWrapper(
(F('views') /Decimal(50.0),
output_field=FloatField()),
)
So, query would look like this:
products = (Media.objects
.exclude(is_deleted=1)
.filter(Q(category__category__in=categories) | Q(tags__tag__title=query))
.annotate(order_count =Count('orders', distinct=True))
.annotate(comment_count =Count('comments', distinct=True))
.annotate(like_count =Count('likes', distinct=True))
.annotate(weight =Count(0))
.annotate(
initial_weight=ExpressionWrapper(
F('order_count') *40+ F('comment_count') *4+
F('like_count') *4+ F('clicks'),
output_field=FloatField()
)
)
.annotate(
views_divided=ExpressionWrapper((F('views') /Decimal(50.0),
output_field=FloatField()))
)
.annotate(weight=F('initial_weight') - F('views_divided'))
.distinct())
Looks ugly, but should work (I think).
On the side note - if you only need to calculate weight
, you don't actually have to use prefetch_related
and select_realted
, django will take care of that stuff itself (however, that's just my speculation - if you actually use those foreign keys later in the code, then it's justified).
Post a Comment for "Django Weighted Query (annotated Values)"