[英]Most efficient Django query to get the objects and their related
我有这个 model:
class Institution(models.Model):
name = models.CharField(max_length=128, db_index=True)
aliases = models.ManyToManyField('self', blank=True)
我想做最有效的查询,返回所有Institution
,其中name
包含搜索词及其aliases
Institution
。 我在该工作下方提供了解决方案,但我想知道是否有更简单/更有效的方法来实现这一目标?
base_query = Institution.objects.filter(name__icontains='term')
pk_query = Q(pk__in=base_query)
aliases_query = Q(aliases__in=base_query)
final_query = Institution.objects.filter(pk_query|aliases_query).distinct()
这是此查询的 SQL:
SELECT DISTINCT `app_institution`.`id`, `app_institution`.`name`
FROM `app_institution` LEFT OUTER JOIN `app_institution_aliases`
ON (`app_institution`.`id` = `app_institution_aliases`.`from_institution_id`)
WHERE (`app_institution`.`id`
IN (SELECT U0.`id` FROM `app_institution` U0 WHERE U0.`name` LIKE %term% )
OR `app_institution_aliases`.`to_institution_id`
IN (SELECT U0.`id` FROM `app_institution` U0 WHERE U0.`name` LIKE %term% ))
ORDER BY `app_institution`.`name` ASC LIMIT 21
通过查看我得到的第一个答案,我认为我应该更清楚地指定我想要的结果。
我想要联合
base_query
的结果( name
包含搜索词的Institution
)和
Institution
的aliases
由base_query
返回(这些aliases
的name
不需要包含搜索词)。以低效(但易于理解)的方式完成将是这样的:
base_query = Institution.objects.filter(name__icontains='term')
results= set(base_query)
for institution in base_query:
results.update(institution.aliases.all())
考虑到 S.Lott 的答案,我终于找到了一种方法来处理我之后加入的两个查询。
base_query = Institution.objects.filter(name__icontains='term')
results= set(base_query)
aliases_query = Institution.objects.filter(aliases__in=base_query)
results.update(aliases_query)
我做了一些小的基准测试,这个解决方案大约需要一个大查询的一半时间。
但是我忘记考虑的是对订购的影响......
像这样的联合查询很困难。
查看用例以确保您确实需要像这样将两个单独的 collections(按名称和别名)混为一谈,这一点很重要。 有时 web 页面可以显示两个 collections,从而无需联合。
使用Q
对象构建“或”条件是创建联合的一种方法。
从这两个查询中组装一个单独的集合是另一种解决方案。
name_query = Institution.objects.filter(name__icontains='term')
aliases_query = Institution.objects.filter(aliases__name__icontains='term')
final_query = list(name_query) + list(aliases_query)
知道哪个更好的唯一方法是对替代品进行基准测试。 SQL 查询文本的“复杂性”实际上并没有多大意义,因为 RDBMS 中有很多优化步骤。
这个:
Institution.objects.filter(name__icontains='term', aliases__name__icontains='terms')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.