Поиск
Распространенная задача для веб-приложений — поиск данных в базе данных по вводу пользователя. В простом случае это может быть фильтрация списка объектов по категории. Более сложный случай может потребовать поиска с весами, категоризацией, выделением, несколькими языками и т. д. Этот документ объясняет некоторые возможные варианты использования и инструменты, которые вы можете использовать.
Мы будем ссылаться на те же модели, что и в Создание запросов.
Сценарии использования
Стандартные текстовые запросы
Для текстовых полей доступен набор операций сопоставления. Например, вы можете разрешить поиск автора следующим образом:
>>> 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/4.2/topics/db/search/