Можно ли объединить два набора запросов, если один из них имеет аннотацию ранга, а другой - нет?

Я пытаюсь написать функцию поиска и не могу понять, как объединить результаты ранжированного и неранжированного поиска.

Допустим, у меня есть следующая модель:

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)
Вернуться на верх