最有效的Django查询来获取对象及其相关内容

时间:2011-07-15 14:36:04

标签: python django

我有这个型号:

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() 。我带来了下面那个工作的解决方案,但我想知道是否有更简单/更有效的方法来实现这个目标?

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

以下是此查询的SQL:

base_query

更新

通过查看我得到的第一个答案,我想我应该更清楚地说明我想要的结果。

我想要

的UNION
  • Institutionname aliases包含搜索字词的结果)

使用

    Institutionbase_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()) 不需要包含搜索字词。< / LI>

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

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)

第二次更新

考虑到S.Lott的回答,我终于找到了一种方法来处理我之后加入的两个查询。

{{1}}

我做了一些小基准测试,这个解决方案占用了一个大问题的一半时间。

但我忘记考虑的是对订购的影响......

2 个答案:

答案 0 :(得分:0)

联盟查询 - 就像这样 - 很难。

重要的是要检查用例,以确保真的需要将两个单独的集合(按名称和别名)混为一谈。有时,网页可以显示两个集合,无需联合。

使用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中有很多优化步骤。

答案 1 :(得分:0)

这样:

Institution.objects.filter(name__icontains='term', aliases__name__icontains='terms')