MongoDB:如何为单个文档投影所有字段类型?

时间:2020-01-27 19:42:54

标签: mongodb types mongodb-query aggregation-framework

我需要检查给定集合中每个文档中的每个字段类型。

虽然我可以为每个字段编写单独的$type命令并分别为每个文档进行匹配,但我想知道是否有一种更优雅,更有效的方式来投影所有字段类型。

3 个答案:

答案 0 :(得分:2)

尝试一下:

db.collection.aggregate([{
    $addFields: {
        types: {
            $arrayToObject: {
            $map:
            {
                input: { $objectToArray: "$$ROOT" },
                as: "each",
                in: { k: '$$each.k', v: { $type: '$$each.v' } }
            }
        }}
    }
}])

收集数据:

/* 1 */
{
    "_id" : ObjectId("5e065992400289966eefb9a8"),
    "username" : "myName",
    "blog" : "myBlog",
    "details" : "myBlogDetails",
    "Object" : {
        "inOneObject" : true
    }
}

/* 2 */
{
    "_id" : ObjectId("5e0659ae400289966eefbc3a"),
    "username" : "othersName",
    "blog" : "not a blog",
    "details" : "useless"
}

结果:

/* 1 */
{
    "_id" : ObjectId("5e065992400289966eefb9a8"),
    "username" : "myName",
    "blog" : "myBlog",
    "details" : "myBlogDetails",
    "Object" : {
        "inObject" : true
    },
    "types" : {
        "_id" : "objectId",
        "username" : "string",
        "blog" : "string",
        "details" : "string",
        "Object" : "object"
    }
}

/* 2 */
{
    "_id" : ObjectId("5e0659ae400289966eefbc3a"),
    "username" : "othersName",
    "blog" : "not a blog",
    "details" : "useless",
    "types" : {
        "_id" : "objectId",
        "username" : "string",
        "blog" : "string",
        "details" : "string"
    }
}

注意::该给定查询仅适用于文档中的顶级字段,它不会使您从字段::

下输入inObject类型
"Object" : {
            "inOneObject" : true
        }

答案 1 :(得分:1)

您需要枚举所有字段并分别处理每个字段。您可以使用$objectToArray$unwind的组合来进行枚举,然后使用$push$arrayToObject来将所有内容重新组合在一起:

db.collection.aggregate([
    // Convert the root document into an array.
    {$project: {
        fields: {
            $objectToArray: "$$ROOT"
        }
    }},

    // Turn each array element into a separate document representing a field-value pair of the root document.
    {$unwind: "$fields"},

    // Apply the $type projection to the value portion of the field-value pair.
    {$project: {
        fields: {
            k: "$fields.k",
            v: {$type: "$fields.v"}
        }
    }},

    // Grab the first instance of each unique field name.
    {$group: {
        _id: "$fields.k",
        fields: {$first: "$fields"}
    }},

    // Take the unique field instances and recollect them all into an array.
    {$group: {
        _id: null,
        fields: {$push: "$fields"}
    }},

    // Convert our array back into an object.
    {$project: {
        fields: {$arrayToObject: "$fields"}
    }},

    // Replace the root document with our nested "fields" sub-document.
    {$replaceRoot: {
        newRoot: "$fields"
    }}
])

一个小警告:如果该字段可能包含多种类型,例如“ string”和“ null”,那么此解决方案将不会解决这种情况。要解决该问题,您需要修改$group阶段以利用$addToSet运算符为每个键$type将其唯一$push实例收集到每个键之前, fields数组。

答案 2 :(得分:-1)

您是否尝试过使用mongo Compass产品?

对于这个要求,我相信这很容易.....