Spec-Zone.ru › Django 2.1

Поиск

Одной из распространенных задач веб-приложений является поиск данных в базе данных по вводу пользователя. В простом случае это может быть фильтрация списка объектов по категории. Более сложный случай может потребовать поиска с весами, категоризацией, выделением, несколькими языками и так далее. Этот документ описывает некоторые возможные варианты использования и инструменты, которые вы можете использовать.

Мы будем ссылаться на те же модели, что и в Выполнение запросов.

Варианты использования

Стандартные текстовые запросы

Для текстовых полей доступно несколько простых операций сопоставления. Например, вы можете разрешить поиск автора следующим образом:

>>> Author.objects.filter(name__contains='Terry')
[<Author: Terry Gilliam>, <Author: Terry Jones>]

Это очень хрупкое решение, так как оно требует, чтобы пользователь знал точную подстроку имени автора. Лучшим подходом может быть нечувствительное к регистру сопоставление (icontains), но это только немного лучше.

Более продвинутые функции сравнения базы данных

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

Поиск в других базах данных

Все инструменты поиска, предоставляемые django.contrib.postgres, построены полностью на общедоступных API, таких как пользовательские сопоставления и функции базы данных. В зависимости от вашей базы данных вы должны иметь возможность создавать запросы, позволяющие аналогичные API. Если есть конкретные вещи, которые нельзя достичь таким образом, пожалуйста, откройте заявку.

В приведенном выше примере мы определили, что поиск, нечувствительный к регистру, будет более полезным. При работе с именами, не относящимися к английскому языку, дальнейшим улучшением является использование unaccented comparison:

>>> Author.objects.filter(name__unaccent__icontains='Helen')
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]

Это показывает еще одну проблему, когда мы ищем по другому написанию имени. В этом случае у нас есть асимметрия — поиск Helen найдет Helena или Hélène, но не наоборот. Другим вариантом было бы использование сравнения trigram_similar, которое сравнивает последовательности букв.

Например:

>>> Author.objects.filter(name__unaccent__lower__trigram_similar='Hélène')
[<Author: Helen Mirren>, <Author: Hélène Joy>]

Теперь у нас есть другая проблема — более длинное имя «Елена Бонем Картер» не отображается, так как оно намного длиннее. Поиск триграмм рассматривает все комбинации из трех букв и сравнивает, сколько из них присутствует как в запросе, так и в исходной строке. Для более длинного имени существует больше комбинаций, которые встречаются в исходной строке, поэтому оно больше не считается близким совпадением.

Правильный выбор функций сравнения здесь зависит от вашего набора данных, например, от используемых языка(ов) и типа искомого текста. Все примеры, которые мы видели, касаются коротких строк, где пользователь, вероятно, введет что-то близкое (по разным определениям) к исходным данным.

Поиск по документам

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

  • Игнорирование «стоп-слов», таких как «a», «the», «and».
  • Сведение слов к основам, так что «pony» и «ponies» считаются похожими.
  • Присвоение весов словам на основе различных критериев, таких как частота их появления в тексте или важность полей, в которых они появляются, например, заголовок или ключевые слова.

Существует много альтернатив использования программного обеспечения для поиска, некоторые из наиболее известных — Elastic и Solr. Это решения для полнотекстового поиска по документам. Для использования их с данными из моделей Django вам потребуется слой, который преобразует ваши данные в текстовый документ, включая обратные ссылки на идентификаторы базы данных. Когда движок поиска возвращает определенный документ, вы можете затем найти его в базе данных. Существует множество сторонних библиотек, которые предназначены для помощи в этом процессе.

Поддержка PostgreSQL

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

Модуль django.contrib.postgres предоставляет некоторые вспомогательные средства для создания этих запросов. Например, простым запросом может быть выбор всех записей блога, в которых упоминается «сыр»:

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

Вы также можете фильтровать по комбинации полей и по связанным моделям:

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

См. документ contrib.postgres Полнотекстовый поиск для получения полной информации.

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

Spec-Zone.ru

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