我在Django中有两个模型:
class Pair(models.Model):
pass
class Person(models.Model):
pair = models.ForeignKey(to=Pair, related_name='mates')
city = models.ForeignKey(to=City)
所以我需要计算来自不同城市的配对频率:
city_a<->city_b: 100
city_a<->city_a: 80
city_b<->city_c: 200
...
对于每个人,我都可以通过以下方式获得另一个人的城市:person.pair.mates.exclude(id=person.id).first()
或类似的东西,所以理论上我可以循环遍历所有Person
实例,然后计算频率,但显然这将非常低效。
但我无法弄清楚如何通过标准查询集获取此信息(如果有办法的话(。欢迎任何提示
您可以注释这些对,例如:
from django.db.models import Count, F, Q
Person.objects.filter(
Q(pair__mates__lt=F('pk')) | Q(pair__mates__gt=F('pk'))
).values(
city1=F('city__name'),
city2=F('pair__mates__city__name')
).annotate(
number=Count('pk')
).order_by('city1', 'city2')
__name
应该是要使用的城市字段。例如,__pk
也可能是一种选择。
查询的工作方式如下:Q(pair__mates__lt=F('pk')) | Q(pair__mates__gt=F('pk'))
通常应排除引用同一Person
的"伙伴"。然后我们使用.values(..)
从城市和pair__mates__city__names
获取name
(或其他归档(。现在我们有了这两个值,我们Count(..)
每组city1
和city2
的记录数。.order_by(..)
是避免下标所必需的,就像qs[1]
从原始Person
查询返回单个记录一样。
因此,查询如下所示:
SELECT app_name_city.name AS city1,
T5.name AS city2,
COUNT(app_name_person.id) AS number
FROM app_name_person
INNER JOIN app_name_pair ON app_name_person.pair_id = app_name_pair.id
INNER JOIN app_name_person T3 ON app_name_pair.id = T3.pair_id
INNER JOIN app_name_city ON app_name_person.city_id = app_name_city.id
INNER JOIN app_name_city T5 ON T3.city_id = T5.id
WHERE T3.id < app_name_person.id OR T3.id > app_name_person.id
GROUP BY app_name_city.name, T5.name
ORDER BY city1 ASC, city2 ASC
这将返回QuerySet
字典:
<QuerySet [
{'city1': 'city_a', 'city2': 'city_a', 'number': 80},
{'city1': 'city_a', 'city2': 'city_b', 'number': 100},
{'city1': 'city_b', 'city2': 'city_c', 'number': 200}
]>