Поиск по иерархичным данным в elasticsearch (и не только)



Представьте, что у вас есть две сущности, которые связаны внешними ключами



Например, в нашем случае такими сущностями выступают

Ticket — обращение пользователя в поддержку: содержит кучу разной метаинфы в виде тегов, кастомных полей

Article — сообщение в рамках одного тикета



Одним из кейсов для поиска является запрос "полнотекстово поискать по тексту артиклов среди тикетов, у которых такие-то метаданные". То есть в поиске участвует как родительская сущность (ticket), так и дочерняя (article)



Если это делать на реляционной БД, то все достаточно просто: накидываем нужные индексы на обе таблицы, и далее в запросах джойним и фильтруем по обоим таблицам. Особо тут ничего не оптимизируешь



Однако если для поиска выделяется отдельная БД (elastic, sphinx, etc.), то появляется проблема — надо как-то перекидывать данные из основной бд в поиск для индексации, и как-то располагать эти данные в индексе



---



Есть два ключевых трейдоффа:



1. Раздельное хранение



В поисковом индексе parent и child сущности хранятся независимо друг от друга



Плюс: быстрая индексация



Если меняется родительская сущность, не надо переиндексировать дочерние



Минус: медленный поиск



Нужно как-то джойнить документы: либо parent-child запросы в эластик, либо application-side джойны. Это довольно слабо масштабируется, и может оочень сильно тормозить поисковые запросы



2. Денормализация



В каждую дочернюю сущность кладем также всю инфу про родительскую сущность



Плюс: быстрый поиск



Вся нужная инфа хранится в одном документе, соотв-но не нужно думать про иерархию, теперь иерархия никак не аффектит скорость поисковых запросов



Минус: долгая индексация, больше данных



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



---



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