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

MongoDB:如何为单个文档投影所有字段类型?,mongodb,types,mongodb-query,aggregation-framework,Mongodb,Types,Mongodb Query,Aggregation Framework,我需要检查给定集合中每个文档中的每个字段类型 虽然我可以为每个字段编写单独的$type命令,并分别为每个文档进行匹配,但我想知道是否有一种更优雅、更高效的方法可以直接投影所有字段类型。您需要枚举所有字段并单独处理每个字段。为了枚举的目的,您可以结合使用$objectToArray和$unwind,然后使用$push和$arrayToObject将所有内容重新分组在一起: db.collection.aggregate([ // Convert the root document into

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


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

您需要枚举所有字段并单独处理每个字段。为了枚举的目的,您可以结合使用
$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
将其放入
字段数组中。

尝试以下操作:

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"
    }
}
结果:

/* 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"
    }
}
注意:此给定查询仅适用于文档中的顶级字段,它不会从以下字段中获取对象的类型:

"Object" : {
            "inOneObject" : true
        }

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


我相信对于这个要求来说这很容易……

这可能正适合我的需要。谢谢你们两位。@Ben:嘿,你们能接受这个吗?这样你们的问题就会被标记为完整的,并有一个有效的答案。。