У меня есть эта модель:
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
UPDATE
Глядя на 2 первых полученных ответа, я думаю, что должен более четко указать, что я хочу в качестве результата.
Я хочу СОЮЗ
- результаты
base_query
(Institution
, где name
содержит поисковый термин)
С
aliases
каждого из Institution
возвращаемых 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())
2-е ОБНОВЛЕНИЕ
Думая об ответе С. Лотта, я наконец-то нашел способ сделать это с помощью двух запросов, которые я объединяю после.
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)
Я сделал несколько небольших тестов, и это решение занимает примерно половину времени по сравнению с одним большим запросом.
Но то, что я забыл принять во внимание, это влияние на порядок ...