Выполните полнотекстовый поиск, используя две модели - PullRequest
1 голос
/ 26 марта 2019

У меня есть две модели 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 перед выполнением этого поиска.

1 Ответ

1 голос
/ 26 марта 2019

Вы можете добавить поле name из класса 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...