Django中统计每个用户的好友数量并按降序展示的方法
如何高效统计用户的好友数量并降序展示?
嘿,我来帮你搞定这个高效统计的问题!首先先明确你的场景:现有Friend模型定义如下:
class Friend(models.Model): to_friend = models.ForeignKey(User) from_friend = models.ForeignKey(User, related_name='owner')
你当前的实现方式是循环每个用户然后单独统计,代码如下:
for user in User.objects.all(): user.friend_set.all().count()
确实,这种方式效率很低——因为每循环一个用户就会发起一次数据库查询,N个用户就会产生N+1次查询(初始的User.objects.all()是1次,每个count()又是1次),也就是大家常说的N+1查询问题,用户量一大就会拖慢系统。
下面给你两种更高效的实现思路,都是把统计工作交给数据库来做,只需要一次查询就能搞定:
1. 统计单向好友数量(比如别人添加当前用户为好友的数量)
如果你的“好友”定义是被他人添加的数量(对应你原来代码中user.friend_set.count()的逻辑),可以用Django的annotate结合Count聚合函数:
from django.db.models import Count # 一次性统计所有用户的好友数量,并按数量降序排列 user_friend_stats = User.objects.annotate( friend_count=Count('friend_set') ).order_by('-friend_count') # 遍历结果使用,每个user对象会多出friend_count属性 for user in user_friend_stats: print(f"用户 {user.username} 的好友数:{user.friend_count}")
为什么高效?
Django会自动生成包含COUNT聚合的SQL语句,让数据库直接完成统计和排序,全程只需要一次数据库请求,相比循环查询的方式,性能提升非常明显,尤其是用户量较大的时候。
2. 统计双向好友数量(发起+被加的总好友数)
如果你的“好友”定义是双向的——既包括当前用户添加的好友,也包括添加当前用户的好友,可以结合Q表达式或者直接合并两个反向关联的统计:
from django.db.models import Count, Q # 方式1:直接合并两个关联的统计结果 user_total_friends = User.objects.annotate( total_friends=Count('friend_set') + Count('owner') ).order_by('-total_friends') # 方式2:用Q表达式过滤后统计(适合需要去重的场景) user_total_friends = User.objects.annotate( total_friends=Count('id', filter=Q(friend_set__isnull=False) | Q(owner__isnull=False), distinct=True) ).order_by('-total_friends')
注意点:
如果Friend模型中存在重复的好友记录(比如同一个用户多次添加对方为好友),记得在Count里加上distinct=True来去重,比如:
# 统计被加好友数量时去重(避免同一个用户多次添加导致统计重复) user_friend_stats = User.objects.annotate( friend_count=Count('friend_set__from_friend', distinct=True) ).order_by('-friend_count')
内容的提问来源于stack exchange,提问作者Michael Zhovtonoh
相关产品推荐
相关产品推荐

