Spec-Zone.ru › Django 5.0

Поиск

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

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

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

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

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

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

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

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

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

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

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

Существует много альтернатив использования программного обеспечения для поиска, наиболее известные из которых — 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/5.0/topics/db/search/

Spec-Zone.ru

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