Применение многоступенчатой ​​группировки в MongoDb Aggregation Framework - PullRequest
1 голос
/ 21 июня 2020

предположим, что у меня есть следующие данные:

[
    { name: "Clint", hairColor: "brown", shoeSize: 8, income: 20000 },
    { name: "Clint", hairColor: "blond", shoeSize: 9, income: 30000 },
    { name: "George", hairColor: "brown", shoeSize: 7, income: 30000 },
    { name: "George", hairColor: "blond", shoeSize: 8, income: 10000 },
    { name: "George", hairColor: "blond", shoeSize: 9, income: 20000 }
]

Я хочу получить следующий результат:

[
    {
        name: "Clint",
        counts: 2,
        avgShoesize: 8.5,
        shoeSizeByHairColor: [
            { _id: "brown", counts: 1, avgShoesize: 8 },
            { _id: "blond", counts: 1, avgShoesize: 9 },
        ],
        incomeByHairColor: [
            { _id: "brown", counts: 1, avgIncome: 20000 },
            { _id: "blond", counts: 1, avgIncome: 30000 },
        ]
    },
    {
        name: "George",
        counts: 3,
        avgShoesize: 8,
        shoeSizeByHairColor: [
            { _id: "brown", counts: 1, avgShoesize: 8 },
            { _id: "blond", counts: 2, avgShoesize: 8.5 },
        ],
        incomeByHairColor: [
            { _id: "brown", counts: 1, avgIncome: 30000 },
            { _id: "blond", counts: 2, avgIncome: 15000 },
        ],
    }
]

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

Сначала я подумал о применении $group с ключом name. и использовать $facet для различных агрегатов. Я думаю, это не сработает, поскольку $facet не использует подмножество из предыдущего $group. Если я сначала использую $facet, мне нужно будет разделить результат на несколько документов.

Есть идеи, как правильно решить мою проблему?

Ответы [ 2 ]

2 голосов
/ 21 июня 2020

Вам нужно double $ group , первый должен агрегироваться по name и hairColor. А второй может строить вложенный массив:

db.collection.aggregate([
    {
        $group: {
            _id: { name: "$name", hairColor: "$hairColor" },
            count: { $sum: 1 },
            sumShoeSize: { $sum: "$shoeSize" },
            avgShoeSize: { $avg: "$shoeSize" },
            avgIncome: { $avg: "$income" },
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $group: {
            _id: "$_id.name",
            count: { $sum: "$count" },
            sumShoeSize: { $sum: "$sumShoeSize" },
            shoeSizeByHairColor: {
                $push: {
                    _id: "$_id.hairColor", counts: "$count", avgShoeSize: "$avgShoeSize"
                }
            },
            incomeByHairColor: {
                $push: {
                    _id: "$_id.hairColor", counts: "$count", avgIncome: "$avgIncome"
                }
            }
        }
    },
    {
        $project: {
            _id: 1,
            count: 1,
            avgShoeSize: { $divide: [ "$sumShoeSize", "$count" ] },
            shoeSizeByHairColor: 1,
            incomeByHairColor: 1
        }
    }
])

Пн go Площадка

0 голосов
/ 21 июня 2020

Фаза 1: Вы можете группировать по name и hairColor и накапливать count, avgShoeSize, avgIncome, hairColors

Фаза 2: Pu sh накапливается в массив incomeByHairColor, incomeByHairColor с использованием оператора $map.

Фаза 3: Наконец, в фазе 3 вы накапливаете группу по имени и суммированию, incomeByHairColor, incomeByHairColor и count

Конвейер:

db.users.aggregate([
    {
        $group :{
            _id: {
                name : "$name", 
                hairColor: "$hairColor"
            }, 
            count : {"$sum": 1},
            avgShoeSize: {$avg: "$shoeSize"},
            avgIncome : {$avg: "$income"},
            hairColors : {$addToSet:"$hairColor" }
        }
    }, 
    {
        $project: {
            _id:0,
            name : "$_id.name",
            hairColor: "$_id.hairColor",
            count : "$count",
            incomeByHairColor : {
                $map: {
                  input: "$hairColors",
                  as: "key",
                  in: { 
                      _id: "$$key", 
                      counts: "$count", 
                      avgIncome: "$avgIncome"
                  }
                }
                
            },
            shoeSizeByHairColor:{
                $map: {
                  input: "$hairColors",
                  as: "key",
                  in: { 
                      _id: "$$key", 
                      counts: "$count", 
                      avgShoeSize: "$avgShoeSize"
                  }
                }
                
            
            }
        }
    },
    {
        $group: {
            _id : "$name",
            count : {$sum:  "$count"},
            incomeByHairColor: {$push : "$incomeByHairColor"},
            shoeSizeByHairColor : {$push : "$shoeSizeByHairColor"}
        }
    }
            
]
)

Вывод:

/* 1 */
{
    "_id" : "Clint",
    "count" : 2,
    "incomeByHairColor" : [
        [
            {
                "_id" : "blond",
                "counts" : 1,
                "avgIncome" : 30000
            }
        ],
        [
            {
                "_id" : "brown",
                "counts" : 1,
                "avgIncome" : 20000
            }
        ]
    ],
    "shoeSizeByHairColor" : [
        [
            {
                "_id" : "blond",
                "counts" : 1,
                "avgShoeSize" : 9
            }
        ],
        [
            {
                "_id" : "brown",
                "counts" : 1,
                "avgShoeSize" : 8
            }
        ]
    ]
},

/* 2 */
{
    "_id" : "George",
    "count" : 3,
    "incomeByHairColor" : [
        [
            {
                "_id" : "blond",
                "counts" : 2,
                "avgIncome" : 15000
            }
        ],
        [
            {
                "_id" : "brown",
                "counts" : 1,
                "avgIncome" : 30000
            }
        ]
    ],
    "shoeSizeByHairColor" : [
        [
            {
                "_id" : "blond",
                "counts" : 2,
                "avgShoeSize" : 8.5
            }
        ],
        [
            {
                "_id" : "brown",
                "counts" : 1,
                "avgShoeSize" : 7
            }
        ]
    ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...