如何在Django中实现多对多关系的Having Count过滤?
问题:获取同时拥有指定标签的用户的Django过滤实现
多次尝试后,我仍无法将这类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;
可以看到,having count(*)操作是基于自动生成的多对多中间表user_tags,标签过滤条件为"user_tags"."tag_id" in (8, 163)。
是否可以用Django原生方式实现?我之前的尝试仅用到user和tag表,从未涉及自动生成的中间表。
补充说明
已将@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),)))
内容的提问来源于stack exchange,提问作者Guillaume Cisco
相关产品推荐
相关产品推荐

