Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何更新一个MongoDB文档的_id?_Mongodb - Fatal编程技术网

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

如何更新一个MongoDB文档的_id?,mongodb,Mongodb,我想更新一个文档的\u id字段。我知道这不是很好的练习。但是由于一些技术原因,我需要更新它 如果我尝试更新它,我会得到: db.clients.update({ _id: ObjectId("123")}, { $set: { _id: ObjectId("456")}}) Performing an update on the path '_id' would modify the immutable field '_id' 并且更新被拒绝。如何更

我想更新一个文档的
\u id
字段。我知道这不是很好的练习。但是由于一些技术原因,我需要更新它

如果我尝试更新它,我会得到:

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

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

并且更新被拒绝。如何更新它?

您无法更新它。您必须使用新的
\u 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")})

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


在本例中,UserId是我想使用的新ID。如果您想在同一个集合中重命名_ID(例如,如果您想在某些_ID前面加前缀):


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

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

您可以轻松地使用以下内容手动创建新想法:
\u id:ObjectId()
但是知道Mongo会自动分配一个_id(如果缺少),您可以使用aggregate创建一个包含文档所有字段的
$project
,但省略字段id。然后您可以使用
$out
保存它

因此,如果您的文档是:

{
"_id":ObjectId("5b5ed345cfbce6787588e480"),
"title": "foo",
"description": "bar"
}
那么您的查询将是:

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

您还可以从MongoDB compass或使用命令创建一个新文档,并设置所需的
specific\u id
值。

是否创建快照()在查找时,建议不要让forEach在迭代时意外拾取较新的文档?此代码段永远不会完成。它会在集合上不断迭代。Snapshot不会达到预期效果(您可以通过拍摄“快照”将文档添加到集合中,然后查看快照中是否有新文档来测试它)有关快照的替代方法,请参阅。
list()
是合乎逻辑的,但对于大型数据库来说,这可能会耗尽内存,这有11次投票,但有人说这是一个无限循环?这是怎么回事?@Andrew,因为当代流行编码器文化要求你在实际验证所说的输入是否有效之前,应该始终确认好的输入。这是一个有趣的问题如果文档上的某个字段具有唯一索引,则此示例将失败。在这种情况下,您的示例将失败,因为无法在唯一索引字段中插入具有重复值的文档。您可以通过先执行“删除”来解决此问题,但这不是一个好主意,因为如果由于某种原因插入失败,您的数据现在将丢失。您必须删除该示例您的索引,执行工作,然后恢复索引。很好@skelly!我碰巧想到了类似的问题,并在2小时前看到了您的最新评论。因此,这种修改id的麻烦被认为是由于允许用户选择id引起的固有问题?如果您在
插入
行中遇到
重复键错误
nd不担心@skelly提到的问题,最简单的解决方案是先调用
remove
行,然后调用
insert
行。对于简单文档,
doc
应该已经打印在您的屏幕上,这样在最坏的情况下,即使insert失败,也很容易恢复。只需使用ObjectId()如果不使用字符串作为参数,将生成一个新的唯一参数。@ShankhadeepGhoshal是的,这是一个风险,特别是当您对一个实时生产系统执行此操作时。不幸的是,我认为您最好的选择是在这个过程中进行计划停机并停止所有写入程序。另一个选择可能不会那么痛苦将强制应用程序暂时进入只读模式。将所有写入数据库的应用程序重新配置为仅指向辅助节点。在此期间,读取将成功,但写入将失败,并且您的数据库将保持静态。
find(…).snapshot不是一个函数,但除此之外,它是一个很好的解决方案。此外,如果您想用自定义id替换
\u id
,您可以检查
doc.\u id.toString().length==24
,以防止无限循环(假设您的自定义id也不是),有趣的想法…但是您通常希望将
\u id
设置为给定的值,而不是让MongoDB生成另一个值。
{
"_id":ObjectId("5b5ed345cfbce6787588e480"),
"title": "foo",
"description": "bar"
}
    db.getCollection('myCollection').aggregate([
        {$match:
             {_id: ObjectId("5b5ed345cfbce6787588e480")}
        }        
        {$project:
            {
             title: '$title',
             description: '$description'             
            }     
        },
        {$out: 'myCollection'}
    ])