Как сортировать по агрегату из другого индекса/типа

У меня есть интернет-магазин, и мне нужно отсортировать по совокупным данным о продажах. Примеры документов на продукцию:

{
    "id": 123,
    "title": "foo product",
    "picture": "https://i.picsum.photos/id/959/200/300.jpghttps://i.picsum.photos/id/959/200/300.jpg"
}

Примеры документов для продажи:

{
    "product_id": 123,
    "date": "2020-01-01",
    "sales": 5
},
{
    "product_id": 123,
    "date": "2020-01-02",
    "sales": 6
},
{
    "product_id": 123,
    "date": "2020-01-03",
    "sales": 2
},
{
    "product_id": 123,
    "date": "2020-01-05",
    "sales": 88
}

Обратите внимание, что дни без продаж не входят в индекс/тип sales.

В настоящее время:

  • Мне нужно отфильтровать все продукты, у которых продажи больше/меньше X за определенный пользователем период времени (и даже возможность фильтровать продажи = 0)
  • Мне нужно отсортировать по возрастанию/убыванию на основе продаж за этот период времени (по возрастанию также будет означать, что он должен начинаться с продуктов без продаж).
  • Мне нужен соответствующий документ продукта также в этом результате
  • Я также должен иметь возможность сортировать по другим полям из индекса продукта.

Как мне это сделать? Мой фон из Solr, и я бы использовал для этого потоковые выражения.

ОБНОВЛЕНИЕ

Я собираюсь назначить награду за это. Я обнаружил, что этого можно добиться, используя агрегации и вложить их.

Если моя структура данных должна быть другой для этого, пожалуйста, опишите. Заранее спасибо!


person Stefan    schedule 26.06.2020    source источник
comment
Нужна ли вам информация о продукте также после сортировки или достаточно только Id. Я предлагаю вам попробовать что-то и добавить это тоже в пост, чтобы избежать отрицательных голосов.   -  person Gibbs    schedule 26.06.2020
comment
Да, мне тоже нужны эти данные. Отредактировал исходный вопрос. Спасибо :)   -  person Stefan    schedule 26.06.2020
comment
У вас была возможность попробовать следующее обновление?   -  person Gibbs    schedule 01.07.2020
comment
Привет @Gibbs, к сожалению, это не помогает с фильтром с 0 продажами или сортировкой по возрастанию продаж, начиная с 0 продаж, хотя я очень ценю вашу помощь!   -  person Stefan    schedule 01.07.2020


Ответы (1)


Объединение двух индексов невозможно в elasticsearch.

Есть пара вариантов:

  1. Тип присоединения — Но это не способ rdbms

  2. Вы можете фильтровать по sales индексу и query обратно с результатами sales запроса в коллекции продуктов, чтобы получить сведения о продукте.

Для сортировки пропущенных значений следует использовать параметр missing. Ссылка

Чтобы получить диапазоны, 3to10, more than 30 вы должны использовать [агрегацию диапазона] (запрос диапазона агрегации elasticsearch)

GET /_search
{
    "aggs" : {
        "sale_ranges" : {
            "range" : {
                "field" : "sales",
                "ranges" : [
                    { "to" : 10 },
                    { "from" : 10, "to" : 20 },
                    { "from" : 20 }
                ]
            }
        }
    }
}

Вы не можете получить продукты без продаж легко. Чтобы получить это,

  1. Вам нужно получить все продукты из таблицы продуктов
  2. Вам нужно получить продукты, отсутствующие в таблице продаж, с помощью вышеуказанного шага.
person Gibbs    schedule 26.06.2020
comment
Есть ли способ объединить подход под 2)? - person Stefan; 26.06.2020
comment
Я не думаю, что есть способ достичь в одном запросе. @Стефан - person Gibbs; 26.06.2020
comment
@Stefan Ссылайтесь и читайте комментарии также. - person Gibbs; 26.06.2020
comment
Это имеет смысл разбить на несколько запросов. Но: что, если я хочу отсортировать по продажам ASC и тем, у кого нет продаж вверху? У меня нет данных для тех, кто в индексе/типе без продаж. - person Stefan; 26.06.2020
comment
во-первых, спасибо за все ваши ответы! Но в данном случае, я думаю, это не сработает. Подход такой: агрегировать все данные из индекса/типа продаж (с датой в определенном диапазоне, суммировать все продажи) и сортировать/фильтровать по ним, а затем извлекать идентификаторы продуктов из первых 50 результатов. Следующим шагом будет поиск этих идентификаторов в индексе/типе продукта. Как я узнаю идентификаторы без каких-либо продаж на первом этапе (помните: я не храню документы для нулевых продаж в день, так как это будет пустой тратой места на диске). Имеет ли это смысл? - person Stefan; 26.06.2020
comment
Да. Вам не нужно хранить документы без продаж в индексе продаж. Да, вы должны использовать нумерацию страниц, например, 50 или около того. Если мой ответ помог, не могли бы вы одобрить. - person Gibbs; 26.06.2020
comment
Конечно, я одобряю :) Что бы вы порекомендовали для сортировки по возрастанию продаж (например, должно начинаться с продаж = 0)? - person Stefan; 26.06.2020
comment
Вы хотите отсортировать продажи. Вы должны использовать сортировку по возрастанию. вот так - person Gibbs; 26.06.2020
comment
Это правда, но как я могу найти идентификаторы с агрегатом sales = 0? Я думаю, что это невозможно. Это будет база для поиска из основного индекса - person Stefan; 26.06.2020
comment
или спросили по-другому: как мне отфильтровать агрегат sales = 0 в индексе/типе продаж и вернуть product_id без каких-либо продаж? - person Stefan; 26.06.2020
comment
Если вы хотите отфильтровать продажи 0 при агрегировании, вы можете использовать query для фильтрации перед агрегированием. - person Gibbs; 26.06.2020
comment
Хотите найти товар без продаж? Вы можете сохранить продажи как 0 в продукте. - person Gibbs; 26.06.2020
comment
Не могли бы вы расширить свой ответ, чтобы он имел рабочий процесс двух запросов, включая возможность сортировки по продажам и фильтрации по продажам во временном диапазоне (например, продажи = 0, продажи = от 3 до 15, более 30 и т. д.)? Я так и не понял вашего комментария по фильтру продаж = 0, как это должно работать? - person Stefan; 29.06.2020
comment
Разве это не возможно с агрегациями? - person Stefan; 01.07.2020
comment
Причина в том, что у вас нет распродажи 0 продуктов в этой коллекции. - person Gibbs; 01.07.2020