我有两个模型,Entity和Tag具有ManyToMany关系:
class Tag(models.Model):
name = models.CharField(max_length=128)
class Entity(models.Model):
name = models.CharField(max_length=128)
tags = models.ManyToManyField(Tag)
在视图中,我具有标签ID的列表,并希望获得排名前10位的实体,其中至少一个标签按其与我的列表共有的标签数量排序。
我目前正在通过'tags__in'进行“至少一个”部分,并在查询集的末尾添加“ .distinct()”。这是正确的方法吗?
我看到注释中有一个'Count'可以包含一些参数,有没有一种方法可以仅在列表中的id时指定?如果不是,我是否需要通过这样的SQL查询(来自文档)?我担心我会损失一些性能。
Blog.objects.extra(
select={
'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
},
)
如果我正确理解了您的问题,我认为此查询应该执行您想要的操作(我正在使用django 3.0):
from django.db.models import Count
Entity.objects.annotate(tag_count=Count("tags", filter=Q(tags__id__in=tag_ids))).filter(
tag_count__gt=0
).order_by("-tag_count")[:10]
生成的SQL(我正在使用postgres):
SELECT "people_entity"."id",
"people_entity"."name",
COUNT("people_entity_tags"."tag_id") FILTER (WHERE "people_entity_tags"."tag_id" IN (1, 4, 5, 8)) AS "tag_count"
FROM "people_entity"
LEFT OUTER JOIN "people_entity_tags"
ON ("people_entity"."id" = "people_entity_tags"."entity_id")
GROUP BY "people_entity"."id"
HAVING COUNT("people_entity_tags"."tag_id") FILTER (WHERE ("people_entity_tags"."tag_id" IN (1, 4, 5, 8))) > 0
ORDER BY "tag_count" DESC
LIMIT 10