如何从文档引用列表中进行批量upsert?

时间:2016-03-15 12:51:08

标签: mongodb

我正在使用$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"
  } ]

1 个答案:

答案 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()

应用Bulk.find.upsert()
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中进行了测试