提问人:Guillaume Cisco 提问时间:7/24/2023 最后编辑:Guillaume Cisco 更新时间:7/24/2023 访问量:32
Django 对多对多进行过滤,并具有计数
Django filter on many to many with having count
问:
经过多次尝试,我无法将这种 sql 查询转换为 django 过滤。 基本上,它检索具有至少 x 个选定标签(和其他过滤器)的所有用户。 在两个标签的情况下,用户需要同时拥有两个标签,我不想检索具有至少一个标签的用户。
以下是我的定义:
class User(models.Model):
name = models.CharField(max_length=64)
tags = models.ManyToManyField(Tag)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Tag(models.Model):
name = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
SQL 查询将如下所示:
SELECT user.id
FROM user
INNER JOIN "user_tags" ON ("user"."id" = "user_tags"."user_id")
AND "user_tags"."tag_id" in (8, 163) group by "user"."id", user_tags.user_id having count(*) = 2
ORDER BY user.id DESC LIMIT 100;
如您所见,该部分是在创建的 m2m 表上完成的,并且标签的过滤也having count(*)
user_tags
"user_tags"."tag_id" in (8, 163)
它可以通过 django 方式实现吗?
我所有的尝试都使用 和 表,从未创建过表。user
tab
谢谢
编辑:将 @preeti-y 作为正确答案传递,因为看起来这是要走的路。
但是出于我的具体情况和性能原因,我直接使用了一种方法,允许我正确地将其与其他过滤器一起传递。RawSQL
Q(id__in=RawSQL(
'''SELECT U0.id FROM "user" U0
INNER JOIN "user_tags" U1 ON (U0."id" = U1."user_id")
WHERE U1."tag_id" IN %s
GROUP BY U0."id"
HAVING COUNT(U1."user_id") = %s''', (tuple(value), len(value),)))
答:
0赞
Preeti Y.
7/24/2023
#1
根据你的查询,在 Django 的方式中,你可以像这样在注解中使用参数:Count()
filter
User.objects.annotate(
matched_tag_count=Count('tags', filter=Q(tags__in=[8, 163]))
).filter(matched_tag_count=2)
评论
0赞
Guillaume Cisco
7/24/2023
这可行,但使用其他过滤器的性能很糟糕。我最后使用了 RawSQL......
评论