Поиск ¶
Распространенной задачей веб-приложений является поиск некоторых данных в базе данных с вводом пользователя. В простом случае это может быть фильтрация списка объектов по категории. Более сложный вариант использования может потребовать поиска с взвешиванием, категоризацией, выделением, несколькими языками и т. Д. В этом документе объясняются некоторые возможные варианты использования и инструменты, которые вы можете использовать.
Мы будем ссылаться на те же модели, что и при выполнении запросов .
Примеры использования ¶
Стандартные текстовые запросы ¶
Текстовые поля имеют набор операций сопоставления. Например, вы можете разрешить поиск автора следующим образом:
>>> Author.objects.filter(name__contains='Terry')
[<Author: Terry Gilliam>, <Author: Terry Jones>]
Это очень хрупкое решение, поскольку оно требует, чтобы пользователь знал точную подстроку имени автора. Лучшим подходом могло бы быть match ( 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>]
Теперь у нас другая проблема - более длинное имя «Хелена Бонэм Картер» не появляется, потому что оно намного длиннее. При поиске по триграмме рассматриваются все комбинации из трех букв и сравнивается их количество в строке поиска и в исходной строке. Для более длинного имени есть больше комбинаций, которые не появляются в исходной строке, поэтому оно больше не считается близким совпадением.
Правильный выбор функций сравнения здесь зависит от вашего конкретного набора данных, например, используемых языков и типа текста, в котором выполняется поиск. Все примеры, которые мы видели, относятся к коротким строкам, где пользователь может ввести что-то близкое (с помощью различных определений) к исходным данным.
Поиск по документам ¶
Стандартные операции с базой данных перестают быть полезным подходом, когда вы начинаете рассматривать большие блоки текста. В то время как приведенные выше примеры можно рассматривать как операции над строкой символов, при полнотекстовом поиске рассматриваются реальные слова. В зависимости от используемой системы, вероятно, будут использоваться некоторые из следующих идей:
- Игнорирование «стоп-слов», таких как «а», «то», «и».
- Ключевые слова, так что «пони» и «пони» считаются одинаковыми.
- Взвешивание слов на основе различных критериев, таких как частота их появления в тексте или важность полей, таких как заголовок или ключевые слова, в которых они появляются.
Существует множество альтернатив для использования программного обеспечения для поиска, наиболее известными из которых являются 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
Полнотекстовый поиск» .