В недавнем проекте мне пришлось добавить полноценные функции поиска текста в уже существующий проект Django, приведенные ниже замечания каких проблем я столкнулся и как я их решил.
Для легкого чтения я перечислил короткие прогулки и ограничения, которые я нашел, за которым следует более подробный журнал.
Этот проект включал загрузку 30 ГБ + CSV в базу данных, включая информацию о книгах; И реализация полного текста поиск по названию этой книги, автор, теги, категории.
- Добавление в FTS с Postgres Super легко –
- Добавить
django.contrib.postgres
в установленных_apps - Выполните поиск как следует
- Добавить
Book.objects.filter(title__search='A little girl')
- Индексирование для повышения производительности
- Добавить
Searchvectorfield
поле к модели
- Добавить
# for pre computed search vectors search_vector = SearchVectorField(null=True, blank=True)
- Создать индекс
class Meta(object): indexes = [ GinIndex(fields=['search_vector']) ]
Увеличение
Work_mem
Работа по умолчанию_Мема Postgres слишком низкая для рядов M +. редактироватьWork_mem
вpostgresql.config
Файл и перезапустите БД. НемногоSed
Команда, если вы используете Docker.Кэширование Я кэшировал целую веб-страницу на экземпляре Redis вместе с определенными запросами, такими как
счет результата
(Очень тяжелый), который будет повторяться для каждой нагрузки страницы поиска, требуется перегрузкаPaginator
сорт иListView
сорт.Увеличение общей памяти, как правило, не требуется, но мой контейнер Docker не хватает памяти для некоторых запросов.
- Сложные запросы были бы действительно медленными, пример
- Сортировка результатов на основе сходства
- Сортировка результатов поиска (aka
Заказ
) на основе количества комментариев на книге или любом другом нетекстовом столбце.
- Немного сложно настроить
- Делая компромисс между соответствующими результатами и максимальными возможными результатами (хорошими для SEO) требует сложных запросов, которые примут слишком ложуще для обработки.
Доступные Варианты
Есть два основных способа достижения этого –
Django Haystack плагин
С этим вы можете интегрировать поисковую систему с вашим приложением Django. У вас есть несколько вариантов, таких как Solr и эластичный поиск по поиску бэкэнда. Они действительно хороши при передаче текстового поиска большого количества документов, но имеет накладные расходы в виде стоимости сервера, накладные расходы на разработку и т. Д.
Полный текстовый поиск PostgreSQL
Postgres имеет полнофункциональную функцию поиска текста, в SQL вам просто нужно добавить
Где
пункт И у вас полностью рабочий текстовый поиск, а на стороне Djangos вы можете использовать.filter
метод. Хотя это не выделенное поисковое приложение, которое имеет много недостатков, для небольших приложений он отлично работает из коробки, но поскольку база данных растет, вам придется сделать подстройку.
Реализация
Конфигурация
Добавить django.contrib.postgres
Для установленных приложений.
# settings.py .... INSTALLED_APPS = [ ... 'django.contrib.postgres', # for fts search ... ] ...
Модель
from django.db import models from django.contrib.postgres.search import SearchVectorField from django.contrib.postgres.indexes import GinIndex class Book(models.Model): title = models.CharField(max_length=300) poster_url = models.URLField() downloads = models.IntegerField() likes = models.IntegerField() comments_count = models.IntegerField() search_vector = SearchVectorField(null=True, blank=True) # for pre computed serch vectors # tags, categories, authors remaining # raw data fields _tags = models.TextField(default="", blank=True) _categories = models.TextField(default="", blank=True) _authors = models.TextField(default="", blank=True) class Meta(object): indexes = [GinIndex(fields=['search_vector'])]
Выше это типичная модель Django Orm, search_vector
Содержит векторное представление книги Название, теги, категории и авторы
; Postgres преобразует как поисковый запрос, так и текстовые поля на векторы, затем сравнивает их для матча, предварительно вычисления вектор поиска и индексируя его с помощью Ginindex
Мы улучшаем скорость запроса.
search_vector
можно вычислить с подведем ниже кода Python,
Book.objects.update(search_vector=SearchVector('title', '_tags', '_categories', '_authors'))
Использование авторов, тегов и категорий, поскольку Textfield помогает загружать огромный файл CSV быстрее.
Вид
Вид был реализован с обзором ListView
Профилирование
После этого я использовал панель инструментов отладки Django, чтобы взглянуть на выполняемые запросы, было 2 основных вопроса.
- Count (*) был медленным для запросов с ~ 100k + результатами
Счет (*)
В SQL – это общеизвестно дорогой операцией в SQL, вы в основном должны просматривать всю таблицу, чтобы сделать это, существуют некоторые обходные пути, такие как хранение подсчета отдельно, частичные индексы, но ничего не применимо к нашему случаю использования.
Я кэшировал запросы для этого
- Время запроса было резко более после определенного увеличения количества результатов поиска.
Оригинал: “https://dev.to/avikki/django-postgres-text-search-for-10m-rows-2c78”