簡體   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