реструктурировать индекс elasticsearch, чтобы разрешить фильтрацию по сумме значений - PullRequest
3 голосов
/ 26 мая 2020

У меня есть список продуктов.

Каждый продукт имеет несколько вариантов (может быть несколько или сотни, каждый имеет цвет и размер, например красный)

Каждый вариант в наличии (в определенном количестве) на нескольких складах (склады аронуд 100).

Склады имеют коды, например, AB, XY, CD и т.д. c.

Если бы у меня был выбор, я бы ' d проиндексируйте его как:

stock: {
  Red: {
    S: { AB: 100, XY: 200, CD: 20 },
    M: { AB: 0, XY: 500, CD: 20 },
    2XL: { AB: 5, XY: 0, CD: 9 }
  },
  Blue: { 
    ...
  }
}

Вот тип запроса клиента, который я могу получить:

Покажите мне все продукты, которые имеют цвет Red.S на складе (минимум 100) на складах AB & XY.

Так что это, вероятно, будет фильтр типа

Red.S.AB > 100 AND Red.S.XY > 100

Я здесь не пишу весь запрос filter, а просто в эластичном c.

Мы также можем получить запросы SUM, например, сумма запасов в AB и XY должна быть> 500.

Это было бы легко с помощью фильтра сценария, например Red.S.AB + Red.S.XY > 500

Проблема в том, что для 100 складов, 100 размеров, 25 цветов легко требуется 100 * 100 * 25 = 250 тыс. Сопоставлений. Elasticsearch просто не может обрабатывать такое количество ключей.

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

Я также открыт для внешних решений, чем elasti c. Мы рельсы / postgres стек.

Ответы [ 2 ]

3 голосов
/ 29 мая 2020

У вас есть индекс продуктов с вариантами, это нормально, но я бы использовал другой индекс для управления всем, что связано с запасами на нескольких складах. Один документ на товар / размер / цвет / склад с соответствующим количеством. Например:

{
  "product": 123,
  "color": "Red",
  "size": "S",
  "warehouse": "AB",
  "quantity": 100
}

{
  "product": 123,
  "color": "Red",
  "size": "S",
  "warehouse": "XY",
  "quantity": 200
}

{
  "product": 123,
  "color": "Red",
  "size": "S",
  "warehouse": "CD",
  "quantity": 20
}
etc...

Таким образом, вы будете гораздо более гибкими при запросах акций, потому что все, что вам нужно, - это фильтровать поля (product, color, size, warehouse) и просто агрегируйте по полю quantity, суммам, средним значениям или тому, что вы могли придумать.

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

Нет скрипта, вложенных документов не требуется.

0 голосов
/ 31 мая 2020

Лучшим возможным решением будет создание отдельных индексов для складов, и каждый индекс склада будет иметь документы. Один документ на продукт / размер / цвет / склад со связанными значениями, например:

{
  "product": 123,
  "color": "Red",
  "size": "S",
  "warehouse": "AB",
  "quantity": 100
}

Это сократит ваши сопоставления на 100 * 25 = 2500 сопоставлений на индекс.

Остальное для других операций, Я чувствую, что @Val упомянул в своем ответе, который довольно впечатляющий и красивый.

Переходя к внешним решениям, я бы сказал, что вы хотите выполнить задачу по хранению данных, их поиску и извлечению. Elasticsearch и Apache Solr - лучшие поисковые системы для выполнения подобных задач. Я не пробовал Apache Solr, но настоятельно рекомендую go с Elasticsearch из-за его возможностей, активной поддержки сообщества и очень быстрого поиска. Поиск также можно ускорить с помощью анализаторов и токенизаторов. Он также имеет некоторые функции, такие как полнотекстовый поиск и поиск на уровне термина, чтобы настроить поиск в соответствии с ситуацией или постановкой проблемы.

...