更新最初为 null 的嵌套属性

问题描述 投票:0回答:2

我的文档中有一个字段可能为空;我想更新该文档的内部字段,如果该字段为空,则将该字段创建为对象。作为演示:

假设文档如下所示:

{
    id: "xyz",
    name: null
}

db.update({id: "xyz"}, {$set: {"name.first": "Joe"}})

现在,在运行时我不知道名称字段是否为空。如果

name
为空,我只想将
{ first: "Joe" }
更新为
name

我实际上是通过 Mongoose 模型来完成此操作,其架构如下:

{
    name: {
         default: null,
         type: {
            first: {
                type: String
            },
            middle: {
                type: String,
            },
            last: {
                type: String,
            },
            display: {
                type: String,
            }
        }
    }
}

有没有一种方法可以在一个查询中执行更新?或者我需要分两步完成(查询以获取

name
的当前值,然后对其进行扩充并设置)?

编辑:这是我在控制台中运行它时得到的结果

> db.users.findAndModify({ query: { _id: ObjectId("596958d60782a56eb3ba3d93") },  update: { '$set': { 'name.display': 'dfgdfgfgf' } }})
2017-07-14T20:13:45.855-0400 findAndModifyFailed failed: {
"value" : {
    "_id" : ObjectId("596958d60782a56eb3ba3d93"),
    "sessionID" : "2bPzS2lqkDxN-3XEQRw60GAB93XODi4Y",
    "profilePhotoURL" : null,
    "name" : null,
    "__v" : 0
},
"errmsg" : "exception: cannot use the part (name of name.display) to traverse the element ({name: null})",
"code" : 16837,
"ok" : 0
} at src/mongo/shell/collection.js:614

> db.users.update({ _id: ObjectId("596958d60782a56eb3ba3d93") }, {$set: {"name.display": "sdfsdfsfd"}})
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
    "code" : 16837,
    "errmsg" : "cannot use the part (name of name.display) to traverse the element ({name: null})"
}
})
mongodb mongoose mongodb-query
2个回答
3
投票

我最近偶然发现了同样的问题,并且我设法使用从版本 4.2 开始随 Mongodb 附带的聚合管道更新功能和$ifNull运算符解决了该问题。

举个例子,如果我有以下文档:

db.test.insertOne({ _id: "foo", a: null })

我想将a设置为一个对象,例如:

a: { b: 1 }

您可以使用以下语句:

db.test.updateOne({_id: "foo"}, [{$set: {'a.b': { $ifNull: [1, 1] } } }])

这样做的目的是,如果 'a.b' 为空或不为空,它将用值 1 更新它。这种方法无需事先知道该字段是否为空或是否已初始化。


-1
投票

使用 MongoDB,您可以使用 findAndModify(),它允许您执行查询并仅更新匹配的文档。

该操作是原子执行的,因此一旦发现没有其他操作可以读取文档,直到更新发生。这在其他情况下很有用。这也是为什么您可以在 API 中调整

writeConcern

示例:

db.collection.findAndModify({
 query: {
  name: null
 },
 update: {
  name: { first: "Joe" }
 }
})
© www.soinside.com 2019 - 2024. All rights reserved.