如何更新一个 MongoDB 文档的 _id?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4012855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 11:50:41  来源:igfitidea点击:

How update the _id of one MongoDB Document?

mongodb

提问by shingara

I want update an _idfield of one document. I know it's not a really good pratice. But with some technical reason, I need update it. If I try to update it I get:

我想更新_id一个文档的字段。我知道这不是一个很好的做法。但由于某些技术原因,我需要更新它。如果我尝试更新它,我会得到:

> db.clients.update({ _id: ObjectId("123")}, { $set: { _id: ObjectId("456")}})

Performing an update on the path '_id' would modify the immutable field '_id'

And the update is not made. How I can update it?

并且没有进行更新。我怎样才能更新它?

回答by Niels van der Rest

You cannot update it. You'll have to save the document using a new _id, and then remove the old document.

你不能更新它。您必须使用 new 保存文档_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")})

回答by Patrick Wolf

To do it for your whole collection you can also use a loop (based on Niels example):

要为您的整个集合执行此操作,您还可以使用循环(基于 Niels 示例):

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

In this case UserId was the new ID I wanted to use

在这种情况下 UserId 是我想使用的新 ID

回答by Mark

In case, you want to rename _id in same collection (for instance, if you want to prefix some _ids):

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

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) {...needed to prevent infinite loop, since forEach picks the inserted docs, even throught .snapshot()method used.

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

回答by Florent Arlandis

Here I have a solution that avoid multiple requests, for loops and old document removal.

在这里,我有一个解决方案,可以避免多个请求、循环和旧文档删除。

You can easily create a new idea manually using something like:_id:ObjectId()But knowing Mongo will automatically assign an _id if missing, you can use aggregate to create a $projectcontaining all the fields of your document, but omit the field _id. You can then save it with $out

您可以使用以下内容轻松手动创建一个新想法:_id:ObjectId()但是知道 Mongo 会在丢失时自动分配一个 _id,您可以使用聚合创建一个$project包含文档所有字段的字段,但省略字段 _id。然后你可以保存它$out

So if your document is:

因此,如果您的文件是:

{
"_id":ObjectId("5b5ed345cfbce6787588e480"),
"title": "foo",
"description": "bar"
}

Then your query will be:

那么您的查询将是:

    db.getCollection('myCollection').aggregate([
        {$match:
             {_id: ObjectId("5b5ed345cfbce6787588e480")}
        }        
        {$project:
            {
             title: '$title',
             description: '$description'             
            }     
        },
        {$out: 'myCollection'}
    ])