尽管给出的答案基本上概述了该方法,但由于支持“批量更新”的实现,您可以使用 MongoDB 2.6 或更高版本执行此类操作。
这仍然是“原子的”独立更新语句。但是您可以一次性“通过网络”提交它们。这至少可以确保更新之间的延迟在服务器上执行时要短得多:
var bulk = db.foo.initializeBulkOrderedOp();
bulk.find({ "site_id": "xxx",
"title.de": { "$exists" false } })
.update({ "$set": { "title.de": "" } });
bulk.find({ "site_id": "xxx",
"content.de": { "$exists" false } })
.update({ "$set": { "content.de": "" } });
bulk.execute();
所以这实际上是到服务器的一次往返,因为所有内容都只发送到 .execute()
但在您目前的形式中(尽管这可能不是您数据的准确表示),您实际上可以“重新构建”以便在单个操作中完成此操作。因此,如果您的文档如下所示:
{
"site_id": "xxx",
"docs": [
{ "title": "a", "content": "a", "lang": "ru" },
{ "title": "b", "content": "b", "lang": "en" }
]
},
{
"site_id": "xxx",
"docs": [
{ "title": "c", "content": "c", "lang": "ru" },
{ "title": "d", "content": "d", "lang": "de" }
]
}
然后按照$addToSet 的规则进行以下工作,其中“set”元素将是“唯一”:
db.foo.update(
{ "site_id": "xxx" },
{ "$addToSet": { "docs": { "title": "d", content: "d", "lang": "de" } } },
{ "multi": true }
)
或者甚至没有逻辑,只检查存在:
db.foo.update(
{ "site_id": "xxx", "docs.lang": { "$ne": "de" } },
{ "$push": { "docs": { "title": "", "content": "", "lang": "de" } } },
{ "multi": true }
)
在最后一种情况下会导致:
{
"_id" : ObjectId("53c936265117367f5ff2038b"),
"site_id" : "xxx",
"docs" : [
{
"title" : "a",
"content" : "a",
"lang" : "ru"
},
{
"title" : "b",
"content" : "b",
"lang" : "en"
},
{
"title" : "",
"content" : "",
"lang" : "de"
}
]
}
{
"_id" : ObjectId("53c936265117367f5ff2038c"),
"site_id" : "xxx",
"docs" : [
{
"title" : "c",
"content" : "c",
"lang" : "ru"
},
{
"title" : "d",
"content" : "d",
"lang" : "de"
}
]
}
因此,您可以选择以不同的方式“处理”事情,或者只是更改您的架构以适应您想要以原子方式进行的更新。