我正在努力优化复杂的 Django 查询,其中我需要跨多个相关模型执行嵌套聚合和条件注释。我想根据用户与帖子的互动来获取前 5 位最活跃的用户,同时还计算不同类型的参与度指标(例如视图、评论和点赞)。
我的模特:
class User(models.Model):
name = models.CharField(max_length=100)
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
created_at = models.DateTimeField()
class Engagement(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
type = models.CharField(max_length=50) # 'view', 'like', 'comment'
created_at = models.DateTimeField()
这是我的代码的样子:
from django.db.models import Count, Q
some_date = ...
top_users = (
User.objects.annotate(
view_count=Count('engagement__id', filter=Q(engagement__type='view', engagement__created_at__gte=some_date)),
like_count=Count('engagement__id', filter=Q(engagement__type='like', engagement__created_at__gte=some_date)),
comment_count=Count('engagement__id', filter=Q(engagement__type='comment', engagement__created_at__gte=some_date)),
total_engagements=Count('engagement__id', filter=Q(engagement__created_at__gte=some_date))
)
.order_by('-total_engagements')[:5]
)
它可以工作,但是查询性能并不理想。对于大型数据集,这种方法会导致查询执行时间变慢,我想知道使用多个
Count
注释和 filter
条件是否有效。
是否有更优化的方法来编写此查询,或者我应该考虑提高性能的任何最佳实践,特别是在处理大量数据时?任何见解或建议都会非常有帮助!
它可以工作,但是查询性能并不理想。对于大型数据集,这种方法会导致查询执行时间变慢,我想知道使用带有过滤条件的多个 Count 注释是否有效。
filter=…
[Django-doc] 方法作为 CASE … WHEN …
实现,因此通常意味着数据库将首先考虑 all 参与,然后过滤掉不满足过滤器的参与在线性扫描中。
但是,如果我们不想在
some_date
之后返回没有任何参与的用户,我们可以通过过滤 JOIN 来提高效率:
top_users = (
User.objects.filter(engagement__created_at__gte=some_date)
.annotate(
view_count=Count('engagement__id', filter=Q(engagement__type='view')),
like_count=Count('engagement__id', filter=Q(engagement__type='like')),
comment_count=Count(
'engagement__id', filter=Q(engagement__type='comment')
),
total_engagements=Count('engagement__id'),
)
.order_by('-total_engagements')[:5]
)
created_at
[Django-doc]:
class Engagement(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
type = models.CharField(max_length=50) # 'view', 'like', 'comment'
created_at = models.DateTimeField(db_index=True)
[Django-doc] 来引用用户模型比使用settings.AUTH_USER_MODEL
模型 [Django- doc]直接。有关更多信息,您可以参阅文档的引用User
模型部分[Django-doc]。User