我正在使用$in
查询进行大量更新。他们看起来像这样:
collection.update(
{ "ref": { "$in": [<list of ObjectIds>] } },
{ "$set": { "foo": "bar" } },
{ "multi" : true, "upsert" : false }
);
这会更新ref
字段关联的所有文档,并将foo
字段设置为“bar”。
问题是我还需要 upsert 行为,以便在此过程中插入并链接任何缺少文档(尚未通过引用链接)。
我可以通过迭代使用各种冗长的方法来实现这一点,但是 我问是否有一个好的,简洁和高效的方法来使用Mongo运算符。
我正在运行Mongo 2.6,因此无法使用任何3.x功能。
为清晰起见而更新:
举一个期望结果的例子。假设一个集合是完全空的,我有两个来自另一个集合的引用:
var refs = [ ObjectId(a), ObjectId(b) ];
我希望upsert填充两个新文档,因此该集合将包含:
[ { "_id": ObjectId(x),
"ref": ObjectId(a), // <- first ref from $in list
"foo": "bar"
},
{ "_id": ObjectId(y),
"ref": ObjectId(b), // <- second ref from $in list
"foo": "bar"
} ]
答案 0 :(得分:2)
请注意,选项"multiple":true
不是.update()
的有效MongoDB选项 - 而是multi:true
。如需进一步说明,请查看update() documentation。
至于你的问题,我个人认为2.6中引入的Bulk Operation Methods可能是实现你想要的最简单方法:
您有一个包含以下元素的数组
x = [1,2,3,4,6]
然后定义批量变量
var bulk = db.collection.initializeUnorderedBulkOp()
在此之后,您循环浏览x[]
中的元素以Bulk.find()并使用Bulk.find.update()
for ( i=0; i < x.length; i++)
{
bulk.find({"ref":x[i]}).upsert().update({$setOnInsert:{"ref":x[i]},$set:{"foo":"bar"}});
}
最后你Bulk.execute()批量
bulk.execute()
上面的update()命令将$set的值为&#34; foo&#34;去&#34;酒吧&#34;如果它匹配&#34;参考&#34;或者如果文档不匹配则插入文档。 $setOnInsert负责创建&#34; ref&#34;插入文档中的值,因为它仅在插入文档时设置。
Bulk Operation Methods的一个优点还在于它报告已插入,插入和更新的内容:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 5,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [
{
"index" : 0,
"_id" : ObjectId("56f0de3d8187bc0dc8faa46b")
},
{
"index" : 1,
"_id" : ObjectId("56f0de3d8187bc0dc8faa46c")
},
{
"index" : 2,
"_id" : ObjectId("56f0de3d8187bc0dc8faa46d")
},
{
"index" : 3,
"_id" : ObjectId("56f0de3d8187bc0dc8faa46e")
},
{
"index" : 4,
"_id" : ObjectId("56f0de3d8187bc0dc8faa46f")
}
]
})
上面的命令和方法已经在MongoDB v2.6.5中进行了测试