Добавим поисковые возможности в блог. Django ORM позволяет проводить базовые операции по поиску совпадений с помощью, например, фильтра contains
(или его версии, учитывающей регистр, icontains
). Следующий запрос можно использовать для поиска постов, содержащих слово framework
в теле:
from blog.models import Post Post.objects.filter(body__contains='framework')
Но если планируется осуществлять сложный поиск с получением результатов, учитывающих схожесть или разный вес у полей, потребуется полнотекстовый поисковый движок.
Django предлагает мощный поиск, созданный на основе полнотекстового поиска из PostgreSQL. Модуль django.contrib.postgres
включает функции, которые есть в PostgreSQL, но которых лишены другие базы данных, поддерживаемые Django. Больше об этом поиске можно узнать здесь: https://www.postgresql.org/docs/10/static/textsearch.html.
Хотя Django и способен работать с любой базой данных, он включает модуль, поддерживающий широкий набор возможностей из PostgreSQL, которых нет в других базах данных, поддерживаемых Django.
Простой поиск
Отредактируйте файл settings.py
проекта и добавьте в пункт INSTALLED_APP
строку django.contrib.postgres
:
INSTALLED_APPS = [
# ...
'django.contrib.postgres',
]
Теперь с помощью search
можно проводить поиск:
from blog.models import Post Post.objects.filter(body__search='django')
Этот запрос использует PostgreSQL для создания направления поиска поля body
и поискового запроса «django». Результаты основаны на сопоставлении направления и запроса.
Поиск в нескольких полях
Иногда может потребоваться искать в нескольких полях. В этом случае нужно определить SearchVector
. Построим вектор, который позволит искать в полях title
и body
модели Post
:
from django.contrib.postgres.search import SearchVector
from blog.models import Post
Post.objects.annotate(
search=SearchVector('title', 'body'),
).filter(search='django')
С помощью annotate
и SearchVector
для обоих полей получается функциональность, которая будет искать совпадения в заголовке и теле постов.
Полнотекстовый поиск — это интенсивный процесс. Если он будет осуществляться в более чем нескольких сотнях строк, нужно определить функциональный индекс, который совпадает с используемым поисковым направлением. Django предлагает поле
SearchVectorField
для моделей. Подробно об этом можно почитать здесь: https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/search/#perfomance.