【问题标题】:Django: Order items according to count of intersecting objects (mutual friends)Django:根据相交对象(共同朋友)的数量对项目进行排序
【发布时间】:2011-10-08 23:34:26
【问题描述】:

我正在使用 Django 编写一个社交网络应用程序,并且需要实现一个类似于 Facebook“Mutual Friends”概念的功能。我有一个像这样的简单模型:

class Friend(models.Model):
    user = models.ForeignKey(User)
    guid = models.BigIntegerField()
    name = models.TextField()

    class Meta:
        unique_together = ['user', 'facebook_id']

它代表了我网站的用户和他的一个朋友之间的关系。 (朋友不一定也是用户)两个用户之间的共同朋友的数量可以计算为他们的朋友列表的交集,换句话说,

users = User.objects.all()
friends = Friend.objects.filter(user=request.user)
friend_ids = [f.guid for f in friends]
for user in users:
    user.mutual = Friend.objects.filter(user=user, guid__in=friend_ids).count()

(执行上述操作的更有效方法将获得奖励积分)。

我的主要问题是,在计算了用户之间的共同朋友数量之后,我现在如何根据当前用户的共同朋友数量订购users 查询集?我不能,在这种情况下,将计数保存为注释或额外字段,因为它依赖于被检查的特定用户以及他所有朋友的某个子集。我可以以某种巧妙的方式使用annotateextra 方法吗?还是raw sql 查询是唯一的方法?如果有,怎么做?

总结

计算每个用户的共同好友数量不是问题。鉴于每个用户的信息,您如何根据该号码继续订购QuerySet

【问题讨论】:

    标签: sql django django-models


    【解决方案1】:

    不确定这是否正是您要寻找的,但是...

    # get current users friends (assuming guid is unique for a friend?)
    user_friend_guids = Friend.objects.values_list('guid', flat=True).filter(user=user)
    
    # get Friend objects where user not current user, is in user_friend_list, group and count by user
    mutual_friends = Friend.objects.values('user__username') \
                                   .filter(guid__in=user_friend_guids).exclude(user=user) \
                                   .annotate(number_mutual_friends=Count('user')) \
                                   .order_by('-number_mutual_friends')
    

    这将返回一个用户名列表,其中包含他们与用户分享的朋友数量,按他们分享的数量排序。

    然后在模板中:

    {% for mutual_friend in mutual_friends %}
        {{mutual_friend.user__username}} - {{mutual_friends.number_mutual_friends}}
    {% endfor %}
    

    【讨论】:

    • 恐怕不是我要找的东西:我希望根据Users 对象的共同朋友数量来排序,而不是Friends 对象.我知道,这是一个小的区别,但给我带来麻烦的是用户的顺序。澄清一下,User 对象是普通的 Django 后端 User 对象,而Friend 定义如上,并不代表实际用户,仅代表我的用户联系人列表中的人。
    • 好的,为了澄清,上面不会返回 Friend 对象。它将返回格式为 [{"user__username":james,"number_mutual_friends":10},{"user__username":herman,"number_mutual_friends":6}] 的列表,因此您将获得用户名列表(或字段您选择)但是是的,正如您提到的,不是用户对象。如果它必须是用户对象,我认为(其他人可能会回答)它需要使用原始 SQL 或通过 python 将共同朋友定义为方法和顺序来完成,例如stackoverflow.com/questions/981375/…
    • 好的,谢谢。不幸的是,使用 python 订购不是一种选择,因为可能有 10000 多个用户。但是,是的,现在想一想,您的方法看起来可能就是所有必要的。我会多玩一点,然后回来(希望有一个解决方案)。谢谢!
    • 是的,我通过使用与您的建议非常相似的方法实现了我的目标,首先选择所有有共同朋友的用户(并计算朋友),然后将查询集附加到所有其他用户的列表中(已选择的除外)。这给出了一个列表,首先按共同的朋友排序,然后是其他参数。这就是我想要的,所以......成功:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多