Рубрики
Без рубрики

Django Postgres Текстовый поиск 10 м + ряды

В недавнем проекте мне пришлось добавить полный текстовый поиск функциональности для уже существующего Django Proje … с меткой Postgres, Django, Python.

В недавнем проекте мне пришлось добавить полноценные функции поиска текста в уже существующий проект Django, приведенные ниже замечания каких проблем я столкнулся и как я их решил.

Для легкого чтения я перечислил короткие прогулки и ограничения, которые я нашел, за которым следует более подробный журнал.

Этот проект включал загрузку 30 ГБ + CSV в базу данных, включая информацию о книгах; И реализация полного текста поиск по названию этой книги, автор, теги, категории.

  1. Добавление в FTS с Postgres Super легко –
    • Добавить django.contrib.postgres в установленных_apps
    • Выполните поиск как следует
Book.objects.filter(title__search='A little girl')
  1. Индексирование для повышения производительности
    • Добавить Searchvectorfield поле к модели
  # for pre computed search vectors
  search_vector = SearchVectorField(null=True, blank=True)  
  • Создать индекс
  class Meta(object):
      indexes = [ GinIndex(fields=['search_vector']) ]
  1. Увеличение Work_mem Работа по умолчанию_Мема Postgres слишком низкая для рядов M +. редактировать Work_mem в postgresql.config Файл и перезапустите БД. Немного Sed Команда, если вы используете Docker.

  2. Кэширование Я кэшировал целую веб-страницу на экземпляре Redis вместе с определенными запросами, такими как счет результата (Очень тяжелый), который будет повторяться для каждой нагрузки страницы поиска, требуется перегрузка Paginator сорт и ListView сорт.

  3. Увеличение общей памяти, как правило, не требуется, но мой контейнер Docker не хватает памяти для некоторых запросов.

  1. Сложные запросы были бы действительно медленными, пример
    • Сортировка результатов на основе сходства
    • Сортировка результатов поиска (aka Заказ ) на основе количества комментариев на книге или любом другом нетекстовом столбце.
  2. Немного сложно настроить
    • Делая компромисс между соответствующими результатами и максимальными возможными результатами (хорошими для 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 основных вопроса.

  1. Count (*) был медленным для запросов с ~ 100k + результатами

Счет (*) В SQL – это общеизвестно дорогой операцией в SQL, вы в основном должны просматривать всю таблицу, чтобы сделать это, существуют некоторые обходные пути, такие как хранение подсчета отдельно, частичные индексы, но ничего не применимо к нашему случаю использования.

Я кэшировал запросы для этого

  1. Время запроса было резко более после определенного увеличения количества результатов поиска.

Оригинал: “https://dev.to/avikki/django-postgres-text-search-for-10m-rows-2c78”