Полнотекстовый поиск ¶
Функции базы данных в модуле 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
( * выражения , config = None , weight = None ) ¶
Поиск в одном поле работает хорошо, но довольно ограничен. Искомые экземпляры 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
( значение , config = None , search_type = 'plain' ) ¶
SearchQuery
переводит термины, предоставленные пользователем, в объект поискового запроса, который база данных будет сравнивать с вектором поиска. По умолчанию все слова, предоставленные пользователем, проходят через алгоритм сегментации, после чего выполняется поиск совпадения для всех полученных терминов.
Если search_type
равно 'plain'
по умолчанию, термины рассматриваются как отдельные ключевые слова. Если search_type
есть 'phrase'
, термины рассматриваются как одно предложение. Если search_type
есть 'raw'
, то вы можете предоставить форматированный поисковый запрос с условиями и операторами. Если search_type
есть
'websearch'
, то вы можете предоставить форматированный поисковый запрос, подобный тому , который используется на веб - поисковых систем. 'websearch'
требуется PostgreSQL ≥ 11. Прочтите документацию по полнотекстовому поиску PostgreSQL, чтобы узнать о различиях и синтаксисе. Примеры:
>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('red tomato') # two keywords
>>> SearchQuery('tomato red') # same results as above
>>> SearchQuery('red tomato', search_type='phrase') # a phrase
>>> SearchQuery('tomato red', search_type='phrase') # a different phrase
>>> SearchQuery("'tomato' & ('red' | 'green')", search_type='raw') # boolean operators
>>> SearchQuery("'tomato' ('red' OR 'green')", search_type='websearch') # websearch operators
Эти термины SearchQuery
можно логически объединить для большей гибкости:
>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('meat') & SearchQuery('cheese') # AND
>>> SearchQuery('meat') | SearchQuery('cheese') # OR
>>> ~SearchQuery('meat') # NOT
См. Раздел « Изменение конфигурации поиска» для объяснения этого параметра config
.
Добавлена поддержка 'websearch'
типа поиска и выражений запросов в
SearchQuery.value
.
SearchRank
¶
-
класс
SearchRank
( вектор , запрос , веса = Нет , нормализация = Нет , плотность_крытия = Ложь ) ¶
Пока что мы вернули результаты, для которых возможно хотя бы одно совпадение между вектором и запросом. Скорее всего, вы захотите отсортировать результаты по некоторому значению релевантности. 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
.
Установите для cover_density
параметра значение, True
чтобы включить ранжирование плотности покрытия, что означает, что учитывается близость совпадающих условий запроса.
Укажите целое число для normalization
параметра, чтобы управлять нормализацией ранга. Это целое число является битовой маской, поэтому вы можете комбинировать несколько вариантов поведения:
>>> from django.db.models import Value
>>> Entry.objects.annotate(
... rank=SearchRank(
... vector,
... query,
... normalization=Value(2).bitor(Value(4)),
... )
... )
В документации PostgreSQL есть более подробная информация о различных вариантах нормализации ранга .
normalization
И cover_density
были добавлены параметры.
SearchHeadline
¶
-
class
SearchHeadline
( выражение , запрос , config = None , start_sel = None , stop_sel = None , max_words = None , min_words = None , short_word = None , highlight_all = None , max_fragments = None , fragment_delimiter = None ) ¶
Принимает одно текстовое поле или выражение, запрос, конфигурацию и набор параметров. Возвращает выделенные результаты поиска.
Установите start_sel
и stop_sel
параметры в строку значений , которые будут использоваться , чтобы обернуть выделенные термины запроса в документе. По умолчанию PostgreSQL имеет значения
<b>
и </b>
.
Обеспечить целые значения к max_words
и min_words
параметрам , чтобы определить длинные и самые короткие заголовки. По умолчанию PostgreSQL имеет значения 35 и 15.
Укажите целочисленное значение short_word
параметра, чтобы исключить слова такой длины или меньше в каждом заголовке. PostgreSQL по умолчанию - 3.
Установите highlight_all
параметр для True
использования всей бумаги вместо фрагмента и неизвестности max_words
, min_words
и short_word
параметров. По умолчанию это отключено в PostgreSQL.
Задайте ненулевое целочисленное значение, чтобы max_fragments
задать максимальное количество отображаемых фрагментов. По умолчанию это отключено в PostgreSQL.
Задайте fragment_delimiter
строковый параметр, чтобы настроить разделитель между фрагментами. По умолчанию PostgreSQL - ." ... "
В документации PostgreSQL есть более подробная информация о выделении результатов поиска .
Пример использования:
>>> from django.contrib.postgres.search import SearchHeadline, SearchQuery
>>> query = SearchQuery('red tomato')
>>> entry = Entry.objects.annotate(
... headline=SearchHeadline(
... 'body_text',
... query,
... start_sel='<span>',
... stop_sel='</span>',
... ),
... ).get()
>>> print(entry.headline)
Sandwich with <span>tomato</span> and <span>red</span> cheese.
См. Раздел « Изменение конфигурации поиска» для объяснения этого параметра config
.
Изменение конфигурации поиска ¶
Можно указать атрибут config
of SearchVector
и of 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
¶
-
класс
SearchVectorField
¶
Если этот подход становится слишком медленным, вы можете добавить поле 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
¶
-
класс
TrigramSimilarity
( выражение , строка , ** дополнительно ) ¶
Принимает имя поля или выражение, а также строку или выражение. Возвращает сходство триграммы между двумя параметрами.
Пример использования:
>>> 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
¶
-
класс
TrigramDistance
( выражение , строка , ** дополнительно ) ¶
Принимает имя поля или выражение, а также строку или выражение. Возвращает расстояние на триграмму между двумя параметрами.
Пример использования:
>>> 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>]