首页 > 解决方案 > Mongo 计算未知数量的字段标签

问题描述

假设我有以下结构:

"KnownName" : {
    "unknownName1" : {
        "id" : "unknownName1",
        "value" : "5"
    },
    "unknownName2" : {
        "id" : "unknownName2",
        "value" : "5"
    },
    "unknownName3" : {
        "id" : "unknownName3",
        "value" : "5"
    },
    "unknownName4" : {
        "id" : "unknownName4",
        "value" : "5"
    },
    "unknownName5" : {
        "id" : "unknownName5_v2",
        "value" : "5"
    },
    "unknownName6" : {
        "id" : "unknownName6",
        "value" : "5"
    }

... many more documents as above in various ways

我想让所有这些都像这样计算:

unknownName1 : 24
unknownName2 : 27
unknownName3 : 10
....
unknownName37 : 12

我确实知道我在“KnownName”节点上的结构,但是在这个节点中我可以有几个不同的标签(这里是 unknownName 1 到 6),但可能或多或少,并且它们可能因文档而异。通常,数组中的 id 将与数组标签具有相同的名称,但它不是给定的(如在 unknownName5 中)。

我一直在寻找对所有这些“未知名称”进行明确计数的方法,但这似乎比预期的更具挑战性。

关于如何实现这一点的任何建议(最好使用聚合框架)

如果有一种简单的方法可以在“KnownName”树中将所有(深层)子级标记为“id”,而无需知道未知的父级名称,它也适用于我。我知道 mongo 中没有通配符之类的东西,但我正在寻找替代 KnownName.*.id 之类的东西

标签: mongodb

解决方案


您需要从$objectToArray开始,因为您的密钥是未知的。然后,您将获得一组键和值,可以使用$group处理这些键和值以获取计数。您还可以使用$replaceRoot$arrayToObject来获取根对象中的动态键

db.col.aggregate([
    {
        $addFields: {
            unknown: { $objectToArray: "$KnownName" }
        }
    },
    {
        $unwind: "$unknown"
    },
    {
        $group: {
            _id: "$unknown.k",
            count: { $sum: 1 }
        }
    },
    {
        $sort: { _id: 1 }
    },
    {
        $group: {
            _id: null,
            data: { $push: { k: "$_id", v: "$count" } }
        }
    },
    {
        $replaceRoot: {
            newRoot: {
                $arrayToObject: "$data"
            }
        }
    }
])

推荐阅读