Относительная частота Mongodb в группировке агрегации - PullRequest
1 голос
/ 20 апреля 2020

У меня есть данные, которые выглядят следующим образом

{"customer_id":1, "amount": 100, "item": "a"}
{"customer_id":1, "amount": 20, "item": "b"}
{"customer_id":2, "amount": 25, "item": "a"}
{"customer_id":3, "amount": 10, "item": "a"}
{"customer_id":4, "amount": 10, "item": "b"}

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

data %>% 
  group_by(customer_id,item) %>%
  summarise(total=sum(amount)) %>% 
  mutate(per_customer_spend=total/sum(total))

Возвращает;

  customer_id item  total per_customer_spend
        <dbl> <chr> <dbl>              <dbl>
1           1 a       100              0.833
2           1 b        20              0.167
3           2 a        25              1    
4           3 a        10              1    
5           4 b        10              1  

Я не могу понять, как сделать это эффективно в понедельник go, лучшее решение, которое у меня есть, - это использование нескольких групп, толкание и разматывание.

1 Ответ

0 голосов
/ 20 апреля 2020

Если вы не хотите изменять структуру данных, нет способа сгруппировать все данные, так как нам нужно определить общую сумму, потраченную каждым пользователем, хотя для этого потребуется всего один $group этап и один * На этапе 1002 * это будет выглядеть примерно так:

db.collection.aggregate([
    {
        $group: {
            _id: "$customer_id",
            total: {$sum: "$amount"},
            rootHolder: {$push: "$$ROOT"}
        }
    },
    {
        $unwind: "$rootHolder"
    },
    {
        $project: {
            newRoot: {
                $mergeObjects: [
                    "$rootHolder",
                    {total: "$total"}
                ]
            }
        }
    },
    {
        $replaceRoot: {
            newRoot: "$newRoot"
        }
    },
    {
        $project: {
            customer_id: 1,
            item: 1,
            total: "$amount",
            per_customer_spend: {$divide: ["$amount", "$total"]}
        }
    }
])

С учетом сказанного, особенно при увеличении масштаба, этот конвейер становится очень дорогим, теперь в зависимости от того, насколько велик масштаб и количество уникальных пар costumer_id x item я бы посоветовал следующее:

учитывая Пн go не любит дублирование данных и предполагая, что пользователь не "покупает" новые элементы слишком часто, возможно, стоит сохранить его как поле в текущая коллекция. (что требует обновления всех предметов пользователя при покупке), я знаю, что это звучит «странно» и дорого, но опять же, в зависимости от частоты покупок, это может стоить. вместо этого создаст новую коллекцию с customer_total и customer_id. Имейте в виду, что это поле все еще потребует поддержки, хотя и намного дешевле. С помощью этой коллекции вы можете либо $ lookup всего (что опять же может быть дорого).

...