我有两张桌子
class User(models.Model):
id = fields.BigIntField(pk=True)
name = CharField(max_length=100)
tags: fields.ManyToManyRelation["Tag"] = fields.ManyToManyField(
"models.Tag", related_name="users", through="user_tags"
)
class Tag(models.Model):
id = fields.BigIntField(pk=True)
name = fields.CharField(max_length=100)
value = fields.CharField(max_length=100)
users: fields.ManyToManyRelation[User]
让我们假设这个虚拟数据
#users
bob = await User.create(name="bob")
alice = await User.create(name="alice")
#tags
foo = await Tag.create(name="t1", value="foo")
bar = await Tag.create(name="t2", value="bar")
#m2m
await bob.tags.add(foo)
await alice.tags.add(foo, bar)
现在我想统计同时拥有
foo
和 bar
标签的用户,在本例中是 alice
,所以应该是 1
。下面的查询将为我提供单级过滤,但如何指定
user
的 foo
中应同时具有 bar
和 tags
?
u = await User.filter(tags__name="t1", tags__value="foo").count()
Tortoise-ORM 提供 Q 对象,用于使用逻辑运算符(如
|
(或)和 &
(和))进行复杂查询。
您的查询可以这样进行:
u = await User.filter(Q(tags__name="t1") &
(Q(tags__value="foo") | Q(tags__value="bar"))).count()
因为目前您无法在 Tortoise ORM 中的带注释字段上进行
group_by
。here引用的
having
子句的解决方案
u = await User.filter(Q(tags__value="foo") | Q(tags__value="bar"))
.annotate(count=Count("id"))
.filter(count==2)
这个想法是获取计数等于标签数量的记录,在本例中为
2
(bar
, foo
)