我试图创建一个查询,并根据权重的自定义计算对其进行排序。Django加权查询(注释值)
我需要一些帮助,因为该解决方案我来确实工作,但性能并不在那里,我想它是
我已经是一个媒体对象。它有相关的评论,喜欢和订单。
什么当前工作,但一个完整的哈克烂摊子以下查询:
products = Media.objects \
.select_related(
'image',
'currency',
'user',
'user__image',
) \
.prefetch_related('category', 'tags') \
.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)) \
.distinct()
for m in products.iterator():
initial_weight = int(m.order_count)*40 + int(m.comment_count)*4 + int(m.like_count)*4 + int(m.clicks)
m.weight = float(float(initial_weight) - float(m.views/50))
正如你看到的,我单独注释我将使用的所有参数,然后做一个愚蠢的迭代全算术针对查询集中每个项目的操作都非常次优。
有一件事我试图做的是以下几点:在注释
products = Media.objects \
.select_related(
'image',
'currency',
'user',
'user__image',
) \
.prefetch_related('category', 'tags') \
.exclude(is_deleted=1) \
.filter(Q(category__category__in=categories) | Q(tags__tag__title=query)) \
.annotate(weight = Count('orders', distinct=True) * 40 + Count('comments', distinct=True) * 4 + Count('likes', distinct=True) - F('views')/50 + F('clicks'))
但类似操作,不可能(试图与不求和()有一些变化 - Django的总是抱怨注解值是不同的型。
通过我们使用Django 1.8本项目的方式。
是否有一个良好的单一查询的形式给出,这是让我所需的排序权重?
编辑:
我的最终解决方案(感谢Назар)
media_list = Media.objects \
.select_related('user', 'user__image', 'image', 'currency') \
.filter(user__in=suggested_users) \
.filter(created_at__gt=seven_days_ago) \
.exclude(sold=True) \
.annotate(order_count = Count('orders', distinct=True)) \
.annotate(comment_count = Count('comments', distinct=True)) \
.annotate(like_count = Count('likes', distinct=True)) \
.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()
非常感谢。 是的,它有点丑,但ExpressionWrapper做的工作! 只有一个音符(有点奇怪)neede dto包裹initial_weight和ExpressionWrapper!我将在最终解决方案中进行编辑。 PS我需要select_related用于其他目的,但它不需要的事实也很有价值!太感谢了。 –
很高兴帮助。如果有人遇到你的问题,我也会更新答案。 –