【问题标题】:Convert ObjectId to String and vice versa inside MongoDB aggregate map在 MongoDB 聚合映射中将 ObjectId 转换为 String,反之亦然
【发布时间】:2017-08-29 13:48:43
【问题描述】:

我在一个集合中有以下文档:

输入:

{
    "_id" : ObjectId("***"),
    "oldItems" : [ 
        {
            "_id" : ObjectId("***"),
            "name" : "ItemId***",
            "nestedItemsToExtract" : { }
        }
    ]
}

我需要遍历 oldItems 数组并使用另一个数组创建一个结果输出文档,其值应从原始数组映射。

输出:

{
    "_id" : ObjectId("***"),
    "newItems" : [ 
        {
            "oldItemId" : "***", // String Value Of Parent's / Mapped Item Id aka ObjectId.toString()
            "_id" : ObjectId("***") // New ObjectId Here aka ObjectId()
        }
    ]
}

如何将映射的(旧)_idObjectId 值转换为字符串,但为结果数组中的(新)_id 属性生成新的 ObjectId?

编辑:

我已经设法找到一种解决方法,通过"{ $literal: ObjectId() }" 表达式生成新的 ObjectId 值。我已经更正了我的“输出”代码 sn-p:

use DB_NAME_HERE

db.getCollection('COLLECTION_NAME_HERE').aggregate([
    { $match: {} },
    { $project: {
        newItems: {
            $map: {
                input: '$oldItems',
                as: 'oldItem',
                in: {
                    oldItemId: '$$oldItem._id' // Returns ObjectId
                    _id: ObjectId() // Fails With 'disallowed field type OID in object expression (at '_id')"'
                    //Edit
                    //_id: { $literal: ObjectId() } // Works
                }
            }
        }       
    }
}])

【问题讨论】:

    标签: mongodb robo3t


    【解决方案1】:

    在当前版本的 Mongodb(3.4) 中,您不能在聚合管道中进行从 ObjectId 到字符串(或反之亦然)的类型转换。 Mongodb 官方错误跟踪器上存在一些指向该问题的问题:

    SERVER-11400: Need a type conversion mechanism to convert between strings and numbers

    SERVER-22781: Allow $lookup between ObjectId (_id.str) and string

    SERVER-24947: Need a type conversion mechanism for booleans, ISODates, ObjectID

    至于 ObjectId 生成期间的错误 - 试试这个:

    use DB_NAME_HERE
    
    db.getCollection('COLLECTION_NAME_HERE').aggregate([
        { $match: {} },
        { $project: {
            newItems: {
                $map: {
                    input: '$oldItems',
                    as: 'oldItem',
                    in: {
                        oldItemId: '$$oldItem._id', // Returns ObjectId
                        _id: { $literal: ObjectId() }
                    }
                }
            }       
        }
    }])
    

    【讨论】:

    • 感谢您提供相应错误/请求的链接。我设法找到了一种通过“{ $literal: ObjectId() }”表达式生成新 ObjectId 值的解决方法。我已经更正了我的“输出”代码 sn-p。您的答案中的“_id: new ObjectId()”表达式也不起作用并产生相同的错误(“对象表达式中不允许的字段类型 OID(在 '_id')”)。请根据以下内容更正您的代码 sn-p我的修改,以便我可以接受您的回答。
    • 我已根据您的解决方法修正了我的答案。但我仍然不明白为什么它在你的情况下不起作用。我前段时间遇到过类似的情况,效果很好。
    猜你喜欢
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多