Зачем полнотекстовый поиск
В уроке про пагинацию и поиск был простой пример SearchVector. Здесь мы углубляемся: config, ранжирование, GinIndex, trigram и подсветка.
icontains ищет подстроку в каждой строке. shoes и shoe для него разные слова, порядка результатов нет, а на большой таблице идёт полный скан. PostgreSQL же превращает текст в лексемы:
SELECT to_tsvector('english', 'Running shoes for runners');
-- 'run':1,5 'shoe':2
SELECT websearch_to_tsquery('english', '"running shoes" -boots');
-- 'run' <-> 'shoe' & !'boot'💡 Полнотекстовый поиск доступен только на PostgreSQL. Добавьте
django.contrib.postgresвINSTALLED_APPS.
SearchVector и SearchQuery
# settings.py
INSTALLED_APPS = [
# ...
"django.contrib.postgres",
"articles",
]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "shop",
# USER, PASSWORD, HOST from environment
}
}from django.contrib.postgres.search import SearchVector
from articles.models import Article
vector = SearchVector("title", "body", config="english")
found = Article.objects.annotate(search=vector).filter(search="django indexes")config выбирает язык текста. Для вектора и запроса он должен совпадать, иначе лексемы могут не совпасть.
from django.contrib.postgres.search import SearchQuery
SearchQuery("red tomato") # plain: all words
SearchQuery("red tomato", search_type="phrase") # words side by side
SearchQuery("red & tomato", search_type="raw") # raw tsquery syntax
SearchQuery('"red tomato" -green', search_type="websearch")