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(..)
这与一个Count(..)
on the locations_of_interest
number:
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
包含与过滤器匹配的兴趣位置的数量。
注意Profile
没有这样的位置的 s 不会出现在查询集中,并且每个Profile
最多会发生一次。
EDIT:计算多个相关的非重叠 (!) 字段
您可以通过计算非重叠连接来扩展此方法,方法是使用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)
)
但请注意,这种方法通常会扩展指数地与数量JOIN
s,所以这通常是not如果您添加数十个或数百个注释,则可扩展。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)