Spec-Zone.ru › Django 2.1

Полнотекстовый поиск

Функции базы данных в модуле django.contrib.postgres.search облегчают использование движка полнотекстового поиска PostgreSQL полнотекстового поиска.

В примерах этого документа мы будем использовать модели, определённые в создании запросов.

См. также

Для общего обзора поиска см. документацию по теме.

Поиск search

Самый простой способ использования полнотекстового поиска — поиск одного термина по одному столбцу в базе данных. Например:

>>> Entry.objects.filter(body_text__search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]

Это создаёт to_tsvector в базе данных из поля body_text и plainto_tsquery из поискового запроса 'Cheese', оба используя стандартную конфигурацию поиска базы данных. Результаты получаются путём сопоставления запроса и вектора.

Для использования поиска search, 'django.contrib.postgres' должен быть в вашем INSTALLED_APPS.

SearchVector

class SearchVector(*expressions, config=None, weight=None) [source]

Поиск по одному полю удобен, но ограничен. Entry объекты, по которым мы ищем, принадлежат Blog, у которой есть поле tagline. Чтобы выполнить запрос по обоим полям, используйте SearchVector:

>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector('body_text', 'blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]

Аргументы для SearchVector могут быть любыми Expression или именем поля. Несколько аргументов будут соединены вместе пробелом, чтобы поисковый документ включал их все.

SearchVector объекты могут быть объединены вместе, что позволяет повторно использовать их. Например:

>>> Entry.objects.annotate(
...     search=SearchVector('body_text') + SearchVector('blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]

См. Изменение конфигурации поиска и Взвешивание запросов для объяснения параметров config и weight.

SearchQuery

class SearchQuery(value, config=None) [source]

SearchQuery преобразует предоставленные пользователем термины в объект поискового запроса, который база данных сравнивает с вектором поиска. По умолчанию, все предоставленные пользователем слова проходят через алгоритмы стемминга, а затем ищет соответствия для всех полученных терминов.

SearchQuery термины могут быть логически объединены для большей гибкости:

>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('meat') & SearchQuery('cheese')  # AND
>>> SearchQuery('meat') | SearchQuery('cheese')  # OR
>>> ~SearchQuery('meat')  # NOT

См. Изменение конфигурации поиска для объяснения параметра config.

SearchRank

class SearchRank(vector, query, weights=None) [source]

Пока мы просто возвращаем результаты, для которых любое соответствие между вектором и запросом возможно. Вероятно, вы захотите упорядочить результаты по некоторому виду релевантности. PostgreSQL предоставляет функцию ранжирования, которая учитывает частоту появления терминов запроса в документе, насколько близко они расположены в документе и насколько важна часть документа, где они встречаются. Чем лучше совпадение, тем выше значение ранга. Чтобы упорядочить по релевантности:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]

См. Взвешивание запросов для объяснения параметра weights.

Изменение конфигурации поиска

Вы можете указать атрибут config для SearchVector и SearchQuery для использования другой конфигурации поиска. Это позволяет использовать различные парсеры языка и словари, как определено в базе данных:

>>> from django.contrib.postgres.search import SearchQuery, SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector('body_text', config='french'),
... ).filter(search=SearchQuery('œuf', config='french'))
[<Entry: Pain perdu>]

Значение config также может храниться в другом столбце:

>>> from django.db.models import F
>>> Entry.objects.annotate(
...     search=SearchVector('body_text', config=F('blog__language')),
... ).filter(search=SearchQuery('œuf', config=F('blog__language')))
[<Entry: Pain perdu>]

Взвешивание запросов

Возможно, каждое поле не имеет одинаковой важности в запросе, поэтому вы можете установить веса различных векторов перед их объединением:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text', weight='A') + SearchVector('blog__tagline', weight='B')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by('rank')

Вес должен быть одной из следующих букв: D, C, B, A. По умолчанию эти веса соответствуют числам 0.1, 0.2, 0.4, и 1.0, соответственно. Если вы хотите взвесить их по-другому, передайте список из четырёх чисел с плавающей точкой в SearchRank в качестве weights в том же порядке, что и выше:

>>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
>>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by('-rank')

Производительность

Специальная конфигурация базы данных не требуется для использования любой из этих функций, однако, если вы ищете более чем в нескольких сотнях записей, вы, вероятно, столкнётесь с проблемами производительности. Полнотекстовый поиск — более ресурсоёмкий процесс, чем сравнение размера целого числа, например.

В случае, если все поля, по которым вы выполняете поиск, содержатся в одной конкретной модели, вы можете создать функциональный индекс, который соответствует вектору поиска, который вы хотите использовать. Документация PostgreSQL содержит подробности о создании индексов для полнотекстового поиска.

SearchVectorField

class SearchVectorField [source]

Если этот подход становится слишком медленным, вы можете добавить SearchVectorField к вашей модели. Вам нужно будет поддерживать его заполненным с помощью триггеров, например, как описано в документации PostgreSQL. Затем вы можете выполнять запросы к полю, как если бы это был аннотированный SearchVector:

>>> Entry.objects.update(search_vector=SearchVector('body_text'))
>>> Entry.objects.filter(search_vector='cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]

Сходство триграмм

Другой подход к поиску — сходство триграмм. Триграмма — это группа из трёх последовательных символов. В дополнение к trigram_similar поиску, вы можете использовать несколько других выражений.

Для их использования вам необходимо активировать расширение pg_trgm в PostgreSQL. Вы можете установить его с помощью операции миграции TrigramExtension.

TrigramSimilarity

class TrigramSimilarity(expression, string, **extra) [source]

Принимает имя поля или выражение и строку или выражение. Возвращает сходство триграмм между двумя аргументами.

Пример использования:

>>> from django.contrib.postgres.search import TrigramSimilarity
>>> Author.objects.create(name='Katy Stevens')
>>> Author.objects.create(name='Stephen Keats')
>>> test = 'Katie Stephens'
>>> Author.objects.annotate(
...     similarity=TrigramSimilarity('name', test),
... ).filter(similarity__gt=0.3).order_by('-similarity')
[<Author: Katy Stevens>, <Author: Stephen Keats>]

TrigramDistance

class TrigramDistance(expression, string, **extra) [source]

Принимает имя поля или выражение и строку или выражение. Возвращает расстояние триграмм между двумя аргументами.

Пример использования:

>>> from django.contrib.postgres.search import TrigramDistance
>>> Author.objects.create(name='Katy Stevens')
>>> Author.objects.create(name='Stephen Keats')
>>> test = 'Katie Stephens'
>>> Author.objects.annotate(
...     distance=TrigramDistance('name', test),
... ).filter(distance__lte=0.7).order_by('distance')
[<Author: Katy Stevens>, <Author: Stephen Keats>]

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.1/ref/contrib/postgres/search/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API