MongoDB:对动态键值对的聚合组操作

时间:2017-01-19 12:46:16

标签: mongodb mapreduce aggregation-framework key-value

我有一个简单的文档,其中一个字段作为键值对。我想在聚合中对这些键执行组操作并添加它们的值。但是这对中的键不是固定的,可以是任何东西。

这是一份示例文件。

{
    _id: 349587843,
    matchPair: {
        3 : 21,
        9 : 4,
        7 : 32
    }
},
{
    _id: 349587478,
    matchPair: {
        7 : 11,
        54 : 32,
        9 : 7,
        2 : 19
    }
}

我想要一个像以下那样的结果。

{
    _id : 3,
    count : 21
},
{
    _id : 9,
    count : 11
},
{
    _id : 7,
    count : 43
},
{
    _id : 54,
    count : 32
},
{
    _id : 2,
    count : 19
}

我有以下查询并尝试使用$unwind操作,但它可能无法正常工作,因为" matchPair"不是一个数组,我不知道要为$sum操作指定什么。

db.MatchPairs.aggregate([
   { "$unwind" : "$matchPair" },
   { "$group" : {
       _id: "$matchPair",
       count : { $sum : $matchPair }
   } }
]);

我也可以尝试使用Map-Reduce,但为此我需要按名称emit()键和值。

我确定这是一个简单的解决方案,但我无法弄明白。

2 个答案:

答案 0 :(得分:1)

: 您可以先使用matchPair投射和重塑$objectToArray字段

  

版本3.4.4的新功能。

{
    $project: {
        matchPair: { $objectToArray: '$matchPair' }
    }
}

那会给

{
    matchPair: [{ k: 3, v: 21 }, { k: 9, v: 4 }, ...] 
}

然后基于$unwind的{​​{1}}

matchPair

那会给

{
    $unwind: '$matchPair'
}

然后{ matchPair: { k: 3, v: 21 } }

$project

那应该给出您想要的输出。一共是

{
    $project: {
        _id: '$matchPair.k',
        count: '$matchPair.v'
    }
}

答案 1 :(得分:0)

$unwind的mongoDb文档中:

  

从输入文档中解构数组字段以输出a   每个元素的文档。

所以你必须改变你的架构,如:

{
    "_id" : ObjectId("5880b57b039a3c89c1db145a"),
    "matchPair" : [ 
        {
            "_id" : "3",
            "count" : 21
        }, 
        {
            "_id" : "9",
            "count" : 4
        }, 
        {
            "_id" : "7",
            "count" : 32
        }
    ]
},
{
    "_id" : ObjectId("5880b58c039a3c89c1db145b"),
    "matchPair" : [ 
        {
            "_id" : "7",
            "count" : 11
        }, 
        {
            "_id" : "54",
            "count" : 32
        }, 
        {
            "_id" : "9",
            "count" : 7
        }, 
        {
            "_id" : "2",
            "count" : 19
        }
    ]
}

然后做:

db.MatchPairs.aggregate([
    { $unwind : "$matchPair" }
]);

将返回:

{
    "_id" : ObjectId("5880b57b039a3c89c1db145a"),
    "matchPair" : {
        "_id" : "3",
        "count" : 21
    }
},
{
    "_id" : ObjectId("5880b57b039a3c89c1db145a"),
    "matchPair" : {
        "_id" : "9",
        "count" : 4
    }
},
{
    "_id" : ObjectId("5880b57b039a3c89c1db145a"),
    "matchPair" : {
        "_id" : "7",
        "count" : 32
    }
},
{
    "_id" : ObjectId("5880b58c039a3c89c1db145b"),
    "matchPair" : {
        "_id" : "7",
        "count" : 11
    }
},
{
    "_id" : ObjectId("5880b58c039a3c89c1db145b"),
    "matchPair" : {
        "_id" : "54",
        "count" : 32
    }
},
{
    "_id" : ObjectId("5880b58c039a3c89c1db145b"),
    "matchPair" : {
        "_id" : "9",
        "count" : 7
    }
},
{
    "_id" : ObjectId("5880b58c039a3c89c1db145b"),
    "matchPair" : {
        "_id" : "2",
        "count" : 19
    }
}

然后你只需进行分组。