Существуют ли другие выражения агрегации mongodb для достижения этого результата?

#mongodb #aggregation-framework

#mongodb — монгодб #aggregation-framework #mongodb

Вопрос:

Существуют ли другие этапы агрегации или выражения для достижения этого результата? Можно ли использовать выражения массива $map и $ reduce для перебора элементов массива и создания новых пар ключ / значение в корне $$?

Мне любопытно узнать, есть ли лучший способ агрегирования этих данных.

Агрегация:

 db.getCollection("test").aggregate([

    { $unwind: "$SubscriptionCharges"},
    { $addFields: { sc: { $objectToArray: "$SubscriptionCharges"} }},

    { $addFields: { cc: { $arrayElemAt: [ { $filter: { input: "$sc", as: "ch", cond:  { $eq: [ "$$ch.k", "ChargeName"]} }}, 0  ]},
                        q: { $arrayElemAt: [ { $filter: { input: "$sc", as: "ch", cond:  { $eq: [ "$$ch.k", "Quantity"]} }}, 0  ]},
                     }    },

    { $addFields: { "cc.k": "$cc.v", "cc.v": "$q.v" }},
    { $addFields: { charges:  {  $arrayToObject: [[ "$cc" ]] }  }},

    { $project: { SubscriptionCharges: 0, sc: 0, cc: 0, q: 0}},
    { $group: { _id: "$_id", CustomerNumber: { $first: "$CustomerNumber"}, CustomerType: { $first: "$CustomerType"}, CustomerName: { $first: "$CustomerName"}, charges: { $mergeObjects: "$charges"} }},
    { $replaceRoot: { newRoot: { $mergeObjects: [ "$$ROOT", "$charges"  ]}}},
    { $project: { charges: 0}}

])
  

Актуально:

  { 
        "_id" : BinData(3, "vRoG6 EVGEOOu6WYALc3VA=="), 
        "CustomerNumber" : "ABC", 
        "CustomerType" : "Direct", 
        "CustomerName" : "Test", 
        "SubscriptionCharges" : [
            {
                "ChargeCode" : "Code-1",
                "Price": 12,
                "ChargeName" : "Name-1", 
                "Quantity" : NumberLong(25), 
            }, 
            {
                "ChargeCode" : "Code-2",
                "Price": 15,
                "ChargeName" : "Name-2", 
                "Quantity" : NumberLong(1), 
            }, 
        ], 
    }
  

Ожидается:

 { 
    "_id" : BinData(3, "vRoG6 EVGEOOu6WYALc3VA=="), 
    "CustomerNumber" : "ABC", 
    "CustomerType" : "Direct", 
    "CustomerName" : "Test", 
    "Name-1": NumberLong(25),
    "Name-2":NumberLong(1)
}
  

Ответ №1:

Вы можете избежать to $unwind с помощью $map a и выполнить непосредственно $replaceRoot для объекта-результата map :

 db.test.aggregate([{
    $replaceRoot: {
        newRoot: {
            $mergeObjects: ["$$ROOT", {
                $arrayToObject: {
                    $map: {
                        input: "$SubscriptionCharges",
                        as: "el",
                        in: {
                            k: "$$el.ChargeName",
                            v: "$$el.Quantity"
                        }
                    }
                }
            }]
        }
    }
}, {
    $project: {
        SubscriptionCharges: 0
    }
}])
  

Это кажется намного проще 🙂

Комментарии:

1. Теперь это то, о чем я говорю 🙂 Спасибо!