python - Django 用交集计数注释查询集

标签 python django django-models django-queryset

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

所以我的问题是:

是否有一种方法可以使用此交集计数来注释配置文件查询集,并以这种方式在数据库中执行操作?

我已经尝试了几种方法,但我认为它们对那些阅读本文并可能知道答案的人没有帮助。

最佳答案

您可以使用 .annotate(..) 执行此操作,并在 locations_of_interest 数字上使用 Count(..):

<b>from django.db.models import Count</b>

matching_profiles = Profile.objects.filter(
    locations_of_interest__in=question.locations.all()
)<b>.annotate(
    locnom=Count('locations_of_interest')
)</b>

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

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

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

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

from django.db.models import Count

matching_profiles = Profile.objects.filter(
    locations_of_interest__in=question.locations.all(),
    <b>industries_of_interest__in=question.industries.all()</b>
)<b>.annotate(
    locnom=Count('locations_of_interest'<b>, distinct=True</b>)<b>,
    indnom=Count('industries_of_interest', distinct=True)</b>
)</b>

但请注意,这种方法通常会随着 JOIN 的数量呈指数级扩展,因此,如果您添加数十个数百个注释。

关于python - Django 用交集计数注释查询集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50555817/

相关文章:

python - 删除字符串之间不需要的空格

python - Gmail API Python - 检索电子邮件正文

python - Django 为 QuerySet 获取可执行的原始 sql

python - 如何获得 restructuredText 以将类添加到每个 html <p> 标记?

django - 在 Django 中建模递归关系的正确方法

python - 根据状态 :Available using Python? 过滤或查询 AWS RDS DBInstances 的正确方法是什么

python - Django:按*仅*年份值过滤日期时间字段?

python - 如何在 Django 的单元测试期间禁用翻译?

python - 如何更改 Django 模型中的选项?

python - 为什么 Django 的用户模型将电子邮件字段设置为非唯一?