Полнотекстовый поиск в Django / PostgreSQL - различные результаты поиска при использовании SearchVector и SearchVectorField в AWS RDS PostgreSQL - PullRequest
2 голосов
/ 19 июня 2019

Я пытаюсь использовать Django SearchVectorField для поддержки полнотекстового поиска. Тем не менее, я получаю другие результаты поиска, когда я использую SearchVectorField в моей модели, а не экземпляр класса SearchVector в моем представлении. Проблема изолирована от экземпляра AWS RDS PostgreSQL. Оба выполняют то же самое на моем ноутбуке.

Позвольте мне попытаться объяснить это с помощью некоторого кода:

# models.py

class Tweet(models.Model):
    def __str__(self):
        return self.tweet_id

    tweet_id = models.CharField(max_length=25, unique=True)
    text = models.CharField(max_length=1000)
    text_search_vector = SearchVectorField(null=True, editable=False)

    class Meta:
        indexes = [GinIndex(fields=['text_search_vector'])]

Я заполнил все строки вектором поиска и установил триггер в базе данных для обновления поля.

# views.py

query = SearchQuery('chance')
vector = SearchVector('text')

on_the_fly = Tweet.objects.annotate(
    rank=SearchRank(vector, query)
).filter(
    rank__gte=0.001
)

from_field = Tweet.objects.annotate(
    rank=SearchRank(F('text_search_vector'), query)
).filter(
    rank__gte=0.001
)

# len(on_the_fly) == 32
# len(from_field) == 0

Набор запросов on_the_fly, который использует экземпляр SearchVector, возвращает 32 результата. Набор запросов from_field, использующий SearchVectorField, возвращает 0 результатов.

Пустой результат побудил меня зайти в оболочку для отладки. Вот некоторые результаты из командной строки в моей среде python manage.py shell:

>>> qs = Tweet.objects.filter(
...     tweet_id__in=[949763170863865857, 961432484620787712]
... ).annotate(
...     vector=SearchVector('text')
... )
>>> 
>>> for tweet in qs:
...     print(f'Doc text: {tweet.text}')
...     print(f'From db:  {tweet.text_search_vector}')
...     print(f'From qs:  {tweet.vector}\n')
... 
Doc text: @Espngreeny Run your 3rd and long play and  compete for a chance on third down.
From db:  '3rd':4 'chanc':12 'compet':9 'espngreeni':1 'long':6 'play':7 'run':2 'third':14
From qs:  '3rd':4 'a':11 'and':5,8 'chance':12 'compete':9 'down':15 'espngreeny':1 'for':10 'long':6 'on':13 'play':7 'run':2 'third':14 'your':3

Doc text: No chance. It was me complaining about Girl Scout cookies. <url-removed-for-stack-overflow>
From db:  '/aggcqwddbh':13 'chanc':2 'complain':6 'cooki':10 'girl':8 'scout':9 't.co':12 't.co/aggcqwddbh':11
From qs:  '/aggcqwddbh':13 'about':7 'chance':2 'complaining':6 'cookies':10 'girl':8 'it':3 'me':5 'no':1 'scout':9 't.co':12 't.co/aggcqwddbh':11 'was':4

Вы можете видеть, что вектор поиска выглядит очень по-разному при сравнении значения из базы данных со значением, сгенерированным с помощью Django.

У кого-нибудь есть идеи относительно того, почему это произойдет? Спасибо!

1 Ответ

1 голос
/ 27 июня 2019

SearchQuery переводит термины, которые пользователь предоставляет, в объект поискового запроса, который база данных сравнивает с вектором поиска. По умолчанию все слова, которые предоставляет пользователь, передаются с помощью алгоритмов Stemming , а затем выполняется поиск совпадений для всех полученных терминов. Здесь нужно решить две проблемы: сначала предоставил информацию об языке алгоритма stemming *.

query = SearchQuery('chance' , config="english")

и второе заменить эту строку

rank=SearchRank(F('text_search_vector'), query)

с

rank=SearchRank('text_search_vector', query)

о пропущенном слове в text_search_vector это стандартная процедура алгоритмов связывания для удаления общего слова, известного как стоп-слово

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...