#python #django #postgresql #full-text-search #django-queryset
#python #django #postgresql #полнотекстовый поиск #django-набор запросов
Вопрос:
У меня есть две модели Item
и Owner
:
class Item(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(
Owner, related_name='owner_items',
on_delete=models.CASCADE,
)
is_featured = models.BooleanField(
choices=CHOICES, default=BOOL_NO
)
# ...
Я выполняю полнотекстовый поиск (на основе документов Django) в полях название элемента и описание. Версия PostgreSQL равна 10.
search_vectors = (
SearchVector('name', weight='A', config='english')
SearchVector('description', weight='B', config='english')
)
terms = [SearchQuery(term) for term in keyword.split()]
search_query = functools.reduce(operator.or_, terms)
search_rank = SearchRank(
search_vectors, search_query, weights=[0.2, 0.4, 0.6, 1]
)
qs = Item.objects.all().annotate(
rank=search_rank
).filter(rank__gte=0.2).order_by('-rank')
Я хочу также ввести поле Owner
, name
в уравнение, также немного повысить ранг, если is_featured
равно true
.
Перед выполнением этого поиска у меня есть Owner
экземпляр model.
Комментарии:
1. если мой ответ решил ваш вопрос, примите его!
Ответ №1:
Вы можете добавить поле name
из class Owner
в search_vector
, возможно, с другим weight
и тем же config
именем (это только гипотеза, потому что вы не указали определение модели владельца или данные).
Способ использовать is_featured
в качестве дополнения для вашего rank
может заключаться в том, чтобы добавить 1 (вы можете использовать другие значения), если это True
так, а затем добавить его к SearchRank
результату.
from django.db import models
from django.db.models import Case, Value, When
from django.contrib.postgres.search import (
SearchQuery, SearchRank, SearchVector,
)
search_vectors = (
SearchVector('name', weight='A', config='english')
SearchVector('description', weight='B', config='english')
SearchVector('owner__name', weight='C', config='english')
)
terms = [SearchQuery(term) for term in keyword.split()]
search_query = functools.reduce(operator.or_, terms)
search_rank = SearchRank(
search_vectors, search_query, weights=[0.2, 0.4, 0.6, 1]
)
qs = Item.objects.all().annotate(
featured_boost=Case(
When(is_featured=True, then=Value(1)),
default=Value(0),
output_field=models.IntegerField(),
)
).annotate(
rank=search_rank featured_boost
).filter(rank__gte=0.2).order_by('-rank')