Можно ли объединить два набора запросов, если один из них имеет аннотацию ранга, а другой - нет?
Я пытаюсь написать функцию поиска и не могу понять, как объединить результаты ранжированного и неранжированного поиска.
Допустим, у меня есть следующая модель:
class Song(models.Model):
filename=models.CharField(max_length=120, db_index=True)
title=models.CharField(max_length=120, db_index=True)
title_vector=SearchVectorField(null=True, blank=True)
Я хотел бы позволить пользователю вводить один поисковый запрос и искать по названию и имени файла. Таким образом, если пользователь вводит "space" в качестве поискового термина, он должен найти любую песню, в названии или имени файла которой есть пробел.
Запрос на векторе заголовка выглядит следующим образом. Идея состоит в том, чтобы упорядочить результаты по рангу, чтобы я мог поместить наиболее релевантные результаты поиска наверх.
title_query_results = Song.objects.annotate(
rank=SearchRank(F('title_vector'), query)
).filter(
title_vector=query
)
Однако запрос имени файла выглядит следующим образом:
file_query_results = Song.objects.filter(
filename__icontains=query
)
Поскольку результаты запроса файла не содержат аннотацию ранга, я не могу выполнить объединение результатов, поскольку они имеют разное количество столбцов.
Есть ли способ получить ранговую аннотацию для запроса по столбцу имени файла?
Если нет, то какие у меня есть возможности для объединения результатов поиска? Например, если я хочу, чтобы все результаты по именам файлов отображались в верхней части списка, как я могу это сделать?
Моя последняя надежда - просто отправить результаты в шаблон в виде отдельных списков, но в идеале шаблон будет иметь только один список результатов запроса для работы.
Вы можете работать с:
from django.db.models import Q
query_results = Song.objects.annotate(
rank=SearchRank(F('title_vector'), query)
).filter(Q(title_vector=query) | Q(filename__icontains=query))
или то же самое, но, возможно, более элегантно:
from django.db.models import Q
query_results = Song.objects.annotate(
rank=SearchRank(F('title_vector'), query)
).filter(title_vector=query, filename__icontains=query, _connector=Q.OR)