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



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

下面是一个示例文档。

{
    _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()键和值。

我确信有一个简单的解决方案,但我无法弄清楚。

:您可以从投影和重塑matchPair领域开始,$objectToArray

版本 3.4.4 中的新功能。

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

这将给

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

然后根据matchPair进行$unwind

{
    $unwind: '$matchPair'
}

这将给

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

然后$project

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

这应该提供您想要的输出。总共将是

.aggregate([
    {
        $project: {
            matchPair: { $objectToArray: '$matchPair' }
        }
    },
    { $unwind: '$matchPair' },
    {
        $project: {
            _id: '$matchPair.k',
            count: '$matchPair.v'
       }
    }
])

在 mongoDb 文档中$unwind

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

因此,您必须更改架构,例如:

{
    "_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
    }
}

然后你只需要做你的分组。

最新更新