Pull to refresh
8
0
Никита @shianmala

Пользователь

Send message

Да, фильтрация происходит по атрибутам, но как вы заметили, не по всем. Поэтому можно немного задублировать информацию по атрибутам для фильтров и для их (атрибутов) отрисовки.

Во-первых, скорее всего, мы получим совершенно разные маппинги для этих задач, а, во-вторых, необходимый объем данных, который нужно хранить для фильтрации (по сути только filter_id: value) в одном индексе, будет меньше, чем тот, что нужен для отрисовки атрибута (название, описание, иконка и тп)

Исходя из этого, кажется, что такая денормализация и дублирование данных может быть вполне приемлемой

это все размещается в блоке query, наверно имелось ввиду различия меж filter и must.

Тут есть трудности с неймингом этих контекстов - пересечения названий query и filter как блоков запроса и одновременно как контекстов выполнения всего запроса. На самом деле на filter и must разделение не заканчивается, также есть например should/must_not, которые также выполняются в разных контекстах) Подробнее об этом можно посмотреть тут https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html#query-context

Я бы порекомендовал еще dynamic: strict в настройках индекса, но это уже вопрос вкусовщины

Согласен, для таких задач, хорошая практика использовать strict мапинг, но так как сам индекс создаём мы же, вероятность добавления новых полей без нашего участия исключена

Да, на первый взгляд, так удобно, но добавляется оверхед.

Плюшевая игрушка - слоник с синим телом и серым хоботом, тогда запрос будет:

Дело чуть больше, чем просто в удобстве: без нестед типа маппинг был расширялся до бесконечности, так как таких filter_id с ростом товаров появляется все больше и больше и невозможно делать их частью маппинга.

Однако, в статье это было упущено, но хранение фильтров мы все-таки немного переосмыслили. Так точные фильтры (которые работают по принципу равенства, без запросов больше/меньше) мы поместили во flattened тип поля (https://www.elastic.co/guide/en/elasticsearch/reference/current/flattened.html) . Он позволяет не использовать nested связи и строить запросы так, будто мы обращаемся к полю в мапинге, при этом не раздувая его:

{
  "query": {
    "bool": {
      "filter": [
        {
           "term":{
             "flattened_filters.хобот": "серый"
           }     
        },
        {
          "term": {
            "flattened_filters.туловище": "синий"
          }
        }
      ]
    }
  }
}

Однако есть ограничения на типы запросов, которые можно делать к таким полям. Поэтому фильтры, по которым делаются запросы больше/меньше, мы храним по той же схеме, что была описана в статье)

Да, на использование нестед полей есть оверхед, но иногда этот маппинг действительно необходим. Плюс запросов с применением фильтров не так много из общей массы запросов, а построение агрегаций фильтров без учёта применённых - очень хорошо подвергаются кэшированию)

все товары храняться под 1 элиасом, а что если шардировать по региону? Да, кол-во алиасов вырастет, но до конечного числа (равное кол-ву регионов). Если проанализировать распределение по регионам, то станет ясно что кол-во документов по каждому региону разниться

В целом - да, шардировать по региону это хорошая идея и мы держим ее в голове на случай, если мы упремся в производительность эластика)

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

Причин на это несколько: первая - нам все еще нужны товары не в наличии для любого региона, вторая - почти любой товар, который доставляется с нашего склада, может быть доставлен в любой регион страны (за некоторыми исключениями). Есть при этом и другие схемы доставок, которые могут работать только в рамках одного региона, но большинство товаров продаётся в том числе и по обычной схеме через склады.

Я думаю, что если и держать копию индекса для отдельных регионов, то имело бы смысл например держать их в разных кластерах ES, получая возможность по-разному масштабировать ресурсы этих кластеров, в зависимости от количества запросов

Хорошее наблюдение и я пожалуй соглашусь, что именно для нашей задачи (без текстового поиска) причин использовать именно ES нет.

Почему же тогда ES? Ответ достаточно прост: в нашем ландшафте нет монги, как следствие нет и боевого опыта ее использования как у разработки, так и у девопсов (да он есть у некоторых людей в отдельности, но массового понимания как ее готовить - нет). Поэтому мы просто не стали брать на себя роль первопроходцев и решили остановиться на более проверенном для нас решении

Как я понял у вас в ES отдельно только важное о товарах

Именно так, и под «важным» мы подразумеваем именно те данные, которые могут влиять на выдачу. То есть все параметры, которые участвуют в фильтрах или сортировках, присутствуют в индексе)

Если я правильно понял, то в первом вопросе речь идёт именно про текстовый поиск товаров, когда большой набор идентификаторов приходит к нам из другого сервиса? При этом верно, что тот «другой» сервис не занимается фильтрацией по цене, но этим занимаемся мы в своём индексе, примерно по той же схеме, что и была описана в вопросе) Пагинацию в такой схеме также делаем мы на своей стороне, что обеспечивает ее работоспособность. Схема имеет много недостатков и прислать в таком виде миллион товаров, конечно будет затруднительно, поэтому мы ограничиваемся более маленькими выдачами.

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

Именно поэтому у нас два индекса:

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

Во втором индексе у нас именно контентная составляющая товара: описания, картинки, атрибуты и тп. Этот индекс можно обновлять реже и вот его данные вполне можно денормализовать, но пока мы не видим в этом необходимости

Именно так и мы и сделали, поместив предложения товара в nested поле, которое позволило делать точные запросы и агрегации по характеристикам предложений)

Но на самом деле решение проблемы рассинхронизации, это trade off между попыткой держать данные в индексе актуальными и «не убивать» кластер постоянным потоком обновлений

Очевидно, что с ростом товарного каталога и количества продавцов, а также с новыми динамическими акциями, пытаться держать индекс в актуальном состоянии по сути означает подвергать индекс постоянным обновлениям, что под капотом приводит к появлению новых сегментов в lucene индексах, что замедляет поиск (заставляя искать в большем количестве сегментов в каждом шарде), а также провоцирует эластик на периодический merge сегментов (дорогая операция в плане cpu/io).

Поэтому мы пытаемся искать золотую середину между обновлениями индекса и возможностью актуализировать цены налету

Заголовок больше для привлечения внимания, но на самом деле, если опуститься к реализации, то все товары хранятся в одном индексе)

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

Принимая это во внимание, мы храним все товары в одном индексе, а коллекции(категории), в которые входит этот товар, храним массивом в документе товара

Можно тоже ссылочку, пожалуйста)

Information

Rating
Does not participate
Location
Новочебоксарск, Чувашия, Россия
Date of birth
Registered
Activity