如何找到那些首选项是给定set preference_list的超集的用户?

时间:2013-04-21 12:44:40

标签: python database django filter django-orm

这是我一直在思考的一个问题,我想听听更有经验的Django开发者的意见,而不是我。说,我有以下模型:

class Preference(models.Model):
    name = models.CharField(max_length=50, unique=True)

class UserProfile(AbstractUser):
    preferences = models.ManyToManyField(Preference, blank=True)

例如,偏好可能与食物有关。我喜欢牛肉和土豆,所以他们会喜欢我。

例如,找到至少拥有牛肉和土豆的用户的最有效方法是什么?所以,我希望找到一个除了牛肉和土豆之外可以在他们的喜好中加入冰淇淋和沙拉的用户。

选项1(迭代):

query = UserProfile.objects.all()   # all user objects

for p in preference_list:           # preference_list contains beef and potatoes
     query = query.filter(preferences__in==p.id)

选项2(DB,伪代码):

SELECT * from UserProfile WHERE preferences is a superset of preference_list

我认为选项2会更有效但我不知道如何在Django中实现它。任何建议或意见如何为这个问题布置模型?

1 个答案:

答案 0 :(得分:0)

您可以应用第一个过滤器来仅保留设置中的偏好设置,然后确保使用Count在设置中包含所有偏好设置:

preferences = ('beef', 'potatoes')
UserProfile.objects.filter(preferences__name__in=preferences
    ).annotate(pref_count=models.Count('preferences')
    ).filter(pref_count=len(preferences)

这确实可以更高效,因为它不会为搜索的每个首选项添加连接(伪代码):

SELECT * FROM userprofile
  LEFT OUTER JOIN userprofile_preferences
  LEFT OUTER JOIN preference
  WHERE preference IN (beef, potato)
  GROUP BY userprofile
  HAVING COUNT(userprofile_preferences) = 2