Полнотекстовый поиск ¶
Функции базы данных в 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
¶
-
class
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
атрибут для 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
¶
-
класс
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>]