Spec-Zone.ru › Django 2.2

Поиск

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

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

Сценарии использования

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

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

>>> 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>]

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

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

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

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

  • Игнорирование «стоп-слов», таких как «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.2/topics/db/search/

Spec-Zone.ru

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