【问题标题】:Django annotate queryset with intersection countDjango用交集计数注释查询集
【发布时间】:2018-05-27 19:36:46
【问题描述】:

Djangonauts,我需要挖掘你的大脑。

简而言之,我有以下三个模型:

class Location(models.Model):
    name = models.CharField(max_length=100)


class Profile(models.Model):
    locations_of_interest = models.ManyToManyField(Location)


class Question(models.Model):
    locations = models.ManyToManyField(Location)

我想查找感兴趣的位置与为特定问题指定的位置相交的所有配置文件。这很简单:

question = Question.objects.first()

matching_profiles = Profile.objects.filter(
    locations_of_interest__in=question.locations.all()
)

但除此之外,我还想知道这些位置重叠到什么程度。

在普通的 python 中,我可以这样做:

question_location_names = [l['name'] for l in question.locations.all()]

for profile in matching_profiles:
    profile_location_names = [l['name'] for l in profile.locations_of_interest.all()]
    intersection = set(question_location_names).intersection(profile_location_names)
    intersection_count = len(list(intersection))
    # then proceed with this number

但是,如果可能的话,在我看来直接在数据库中进行操作似乎是有利的。

TL;DR

所以我的问题是:

有没有办法用这个交集计数注释配置文件查询集,然后在数据库中进行操作?

我尝试了几件事,但我认为它们对阅读本文并可能知道答案的人没有帮助。

【问题讨论】:

    标签: python django django-models django-queryset


    【解决方案1】:

    您可以在locations_of_interest 号码上使用Count(..) 执行此操作:

    from django.db.models import Count
    
    matching_profiles = Profile.objects.filter(
        locations_of_interest__in=question.locations.all()
    ).annotate(
        locnom=Count('locations_of_interest')
    )

    现在每个matching_profiles 实例都有一个名为locnom 的属性,其中包含与过滤器匹配的兴趣位置的数量。

    请注意,没有这些位置的Profiles 将不在查询集中,并且每个Profile 最多会出现一次。

    编辑:计算多个相关的非重叠 (!) 字段

    您可以通过使用distinct=True 计算非重叠连接来扩展此方法:

    from django.db.models import Count
    
    matching_profiles = Profile.objects.filter(
        locations_of_interest__in=question.locations.all(),
        industries_of_interest__in=question.industries.all()
    ).annotate(
        locnom=Count('locations_of_interest', distinct=True),
        indnom=Count('industries_of_interest', distinct=True)
    )

    但是请注意,这种方法通常会随着JOINs 的数量指数扩展,因此如果您要添加数十个我们数百个注释,这通常不可扩展.

    【讨论】:

    • 这确实有效,谢谢。然而,似乎不起作用的是使用第二个属性来使用相同的技巧,例如Profile 上的industries_of_interestQuestion 上的industries,同时。你知道吗?
    • @creimers:我认为你可以通过在计数中使用distinct=True 来解决这个问题。 (Counts.
    • ?叮咚。现在我准备好了。不会添加超过这两个注释。丹克珠宝。
    • 在没有过滤的情况下有什么方法可以做到这一点?如果我仍然想显示所有配置文件,即使它们不在问题位置,但仍然通过位置的交叉点进行注释,以便我可以对交叉点的计数进行排序,该怎么办?是否必须将两个查询链接在一起?
    • 编辑:把它变成自己的问题:stackoverflow.com/questions/51504634/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 2016-03-16
    • 2011-04-08
    • 2019-12-30
    • 2019-03-20
    • 2016-08-17
    • 2020-05-14
    相关资源
    最近更新 更多