繁体   English   中英

最有效的 Django 查询以获取对象及其相关

[英]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

  • 每个Institutionaliasesbase_query返回(这些aliasesname不需要包含搜索词)。

以低效(但易于理解)的方式完成将是这样的:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM