我有一个看起来类似的东西,对唯一索引文件bars.name
:
{ name: 'foo', bars: [ { name: 'qux', somefield: 1 } ] }
。 我想要么更新的子文档,其中{ name: 'foo', 'bars.name': 'qux' }
和$set: { 'bars.$.somefield': 2 }
或创建一个新的子文档与{ name: 'qux', somefield: 2 }
下{ name: 'foo' }
是否有可能做到这一点使用与UPSERT单个查询,或将我必须发出两个独立的吗?
相关阅读: “UPSERT”嵌入文档中 (建议更改架构有子文件标识符为重点,但这是从两年前开始,如果有更好的解决方案,现在我不知道。)
没有确实没有更好的解决这一点,所以也许解释。
假设你有一个适当的文件为您展示的是具有结构:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
如果你喜欢这款更新
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
然后,因为匹配的文件被发现一切都很好。 但是,如果你改变“bars.name”的价值:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
然后你会得到一个失败。 已真的在这里唯一改变的是,在MongoDB的2.6和上述错误是有点更简洁:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16836,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: bars.$.somefield"
}
})
这是在某些方面更好,但你真的不想要“UPSERT”反正。 你想要做什么元素添加到“名称”目前不存在数组。
所以,你真正想要的是“结果”,从没有“更新插入”标志的更新尝试,看看是否有文件受到影响:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
得到响应:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
因此,当修改后的文件是0
,那么你知道你想发出以下更新:
db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
实在没有其他办法可以做到正是你想要的。 由于增加的阵列是不是严格意义上的“设置”类型的操作,您不能使用$addToSet
与组合“批量更新”功能的出现,让你可以“级联”你的更新请求。
在这种情况下,它好像你需要检查的结果,或以其他方式接受阅读整个文档,并检查是否更新或代码中插入一个新的数组。
如果你不介意更改架构了一下,有像这样的结构:
{ "name": "foo", "bars": { "qux": { "somefield": 1 },
"xyz": { "somefield": 2 },
}
}
您可以在一个去执行你的操作。 重申嵌入文档中的“更新插入”的完整性
没有一个方法来做到这一点,如果所述更新依赖于一个参考记录被更新(例如,更新X => X + 1)。 发出2个独立的命令(设置然后插入)导致无法通过因重复检查重复,因为如果你的插件被拒绝来解决竞争条件,你会失去你的更新(效果例如,x不会可以在上面的例子中适当地递增)。 将是很好,如果MongoDB的添加此功能,因为要实现嵌入式文件是一个大抽奖,MongoDB的某些应用程序的能力。