2010-10-25 238 views
91

我想更新一个文档的_id MongoDB。我知道这不是一个很好的实践。但是由于某些技术原因,我需要更新它。但是,如果我尝试更新它,我有:如何更新一个MongoDB文档的_id?

> db.clients.update({'_id':ObjectId("4cc45467c55f4d2d2a000002")}, {'$set':{'_id':ObjectId("4c8a331bda76c559ef000004")}}); 
Mod on _id not allowed 

并且不进行更新。我如何才能真正更新它?

回答

152

您无法更新它。您必须使用新的_id保存文档,然后删除旧文档。

// store the document in a variable 
doc = db.clients.findOne({_id: ObjectId("4cc45467c55f4d2d2a000002")}) 

// set a new _id on the document 
doc._id = ObjectId("4c8a331bda76c559ef000004") 

// insert the document, using the new _id 
db.clients.insert(doc) 

// remove the document with the old _id 
db.clients.remove({_id: ObjectId("4cc45467c55f4d2d2a000002")}) 
+18

如果该文档上的某个字段具有唯一索引,则会出现一个有趣的问题。在这种情况下,您的示例将失败,因为文档无法在唯一索引字段中插入重复值。您可以通过先执行删除来修复此问题,但这不是一个好主意,因为如果您的插入由于某种原因失败,您的数据将丢失。您必须删除索引,执行工作,然后恢复索引。 – skelly 2014-06-02 19:52:52

+0

好点@skelly!我碰巧想到类似的问题,并在2小时前看到了您的新评论。所以这个修改id麻烦被认为是允许用户选择ID导致的内在问题? – RayLuo 2014-06-02 21:56:30

+0

如果在'insert'行中出现'重复键错误',并且不担心提到的@skelly问题,最简单的解决方法是先调用'remove'行,然后调用'insert'行。 “doc”应该已经打印在屏幕上,因此对于简单的文档,它很容易恢复,即使插入失败也是最糟糕的情况。 – philfreo 2015-04-14 19:55:03

22

要为您的整个集合做它,你也可以使用一个循环(基于尼尔斯为例):

db.status.find().forEach(function(doc){ 
    doc._id=doc.UserId; db.status_new.insert(doc); 
}); 
db.status_new.renameCollection("status", true); 

在这种情况下,用户ID是新的ID我想用

+1

发现快照()时,建议让forEach在迭代时意外拾取较新的文档? – 2014-05-14 21:04:38

+0

此代码段永远不会完成。它不断重复收集整个集合。快照并不符合您的期望(您可以通过将快照添加到集合中进行测试,然后看到该新文档位于快照中) – Patrick 2015-01-16 10:01:08

+0

请参阅http://stackoverflow.com/a/28083980/305324获取快照的替代方法。'list()'是合乎逻辑的,但对于大型数据库来说,这可能会耗尽内存 – Patrick 2015-01-22 08:15:36

0

如果您想在同一个集合中重命名_id(例如,如果您想以某些_ids为前缀):

db.someCollection.find().snapshot().forEach(function(doc) { 
    if (doc._id.indexOf("2019:") != 0) { 
     print("Processing: " + doc._id); 
     var oldDocId = doc._id; 
     doc._id = "2019:" + doc._id; 
     db.someCollection.insert(doc); 
     db.someCollection.remove({_id: oldDocId}); 
    } 
}); 

if(doc._id.indexOf(“2019:”)!= 0){...需要防止无限循环,因为forEach挑选插入的文档,即使通过使用.snapshot()方法。