Как создать индекс в ElasticSearch с фильтрами по полям, которые содержат тысячи значений?

У нас есть основное хранилище данных на базе MySql, где хранятся информация о пользователях, их друзьях, видео и просмотрах видео. Нам необходимо реализовать поиск видео по описанию (в поле videos.description) с возможностью фильтрации по видео друзей и не просмотренным видео. 

Учитывая предполагаемые объемы данных: около 10 миллионов пользователей, у каждого из которых несколько тысяч друзей, а также 30-50 миллионов видео, мы ранее использовали elasticSearch для подобных задач. Однако в тех случаях не было такой высокой динамики изменения списка друзей и такого объема данных (вложенные поля с тысячами значений или массивы на тысячи значений). 

Сейчас я задумался, стоит ли полностью перенести данные в elasticSearch, дублируя для каждого видеоролика списки друзей автора и информацию о просмотрах, или же следует рассмотреть смешанное решение с использованием и MySQL, и elasticSearch. Я также изучал возможность использования join field в elasticSearch, но это решение не очень популярно и имеет свои ограничения. Как поступить в этой ситуации?
  • 23 января 2025 г. 7:14
Ответы на вопрос 2
В вашей ситуации важно тщательно подойти к архитектуре решения, чтобы обеспечить максимально эффективный поиск и фильтрацию данных. Рассмотрим несколько подходов.

### 1. Полный перенос данных в Elasticsearch

**Плюсы:**
- Производительность. Elasticsearch специально разработан для быстрого поиска и может эффективно обрабатывать большой объем данных.
- Гибкость запросов. Вы можете легко реализовать сложные фильтры и агрегации.

**Минусы:**
- Дублирование данных. Вам нужно будет синхронизировать данные между MySQL и Elasticsearch, что может быть сложным. Например, при изменении списка друзей нужно обновлять документы в ES.
- Увеличение объема данных. Большое количество дублирующихся данных может привести к увеличению хранилища.

### 2. Гибридный подход

Используйте MySQL для хранения основной информации о пользователях, их друзьях и видео, а Elasticsearch для поиска и фильтрации.

**Плюсы:**
- Не нужно дублировать всю информацию. Например, вы можете хранить список друзей и просмотров в MySQL и только индексы видео в Elasticsearch.
- Можно хранить только данные, необходимые для поиска в Elasticsearch, что уменьшает объем хранимых данных.

**Минусы:**
- Вам придется делать дополнительные запросы к MySQL для получения информации о друзьях и их видео, что может увеличить время отклика.
- Сложность в реализации. Вам нужно будет обеспечить синхронизацию данных между двумя системами.

### 3. Использование `join` в Elasticsearch

Как вы уже отметили, `join` в Elasticsearch не очень популярен и имеет свои ограничения, в частности, он плохо работает с большим объемом данных. Для вашей задачи эластичное решение с `join` может затруднить быструю фильтрацию.

### Рекомендации

1. **Начните с гибридного подхода.** Используйте Elasticsearch для индексации видео по описанию и для фильтрации по полям, таким как `friends_ids` и `watched_ids`. Сохраняйте эти поля в Elasticsearch как массивы или вложенные документы.

2. **Проектируйте индексы правильно.** Индексируйте данные, чтобы минимизировать дублирование и объем данных. Например, вместо хранения каждого друга отдельно в каждом видео попробуйте хранить только идентификаторы друзей, что уменьшит размер данных.

3. **Обновление данных.** Разработайте стратегию обновлений, чтобы синхронизировать изменения из MySQL в Elasticsearch. Это может быть сделано через слушателей изменений в базе данных (например, триггеры в MySQL) или с периодическими заданиями.

4. **Тонкая настройка.** После внедрения мониторьте производительность и дорабатывайте индексы и запросы, чтобы оптимизировать время отклика и нагрузки на систему.

5. **Тестирование.** Проведите тестирование под нагрузкой, чтобы убедиться, что подход работает эффективно для ваших объемов данных.

Таким образом, сочетание возможностей MySQL и Elasticsearch может обеспечить хорошую производительность и гибкость, не жертвуя целостностью данных.
Дублировать список друзей автора это не очень хорошее решение. 
Смотрите в сторону lookup фильтров. https://www.elastic.co/guide/en/elasticsearch/refe...

Вам нужно будет создать отдельный индекс с одним документом на пользователя, в котором список его друзей.
Похожие вопросы