Как обновить _id одного документа MongoDB?
Я хочу обновить поле _id
одного документа. Я знаю, что это не очень хорошая практика. Но по какой-то технической причине мне нужно обновить его. Если я пытаюсь обновить его, я получаю:
> db.clients.update({ _id: ObjectId("123")}, { $set: { _id: ObjectId("456")}})
Performing an update on the path '_id' would modify the immutable field '_id'
И обновление не сделано. Как я могу его обновить?
Ответы
Ответ 1
Вы не можете его обновить. Вам нужно будет сохранить документ с помощью нового _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")})
Ответ 2
Чтобы сделать это для всей вашей коллекции, вы также можете использовать цикл (на основе примера Niels):
db.status.find().forEach(function(doc){
doc._id=doc.UserId; db.status_new.insert(doc);
});
db.status_new.renameCollection("status", true);
В этом случае UserId был новым идентификатором, который я хотел использовать
Ответ 3
В случае, если вы хотите переименовать _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().
Ответ 4
Здесь у меня есть решение, позволяющее избежать множественных запросов на удаление циклов и старых документов.
Вы можете легко создать новую идею вручную, используя что-то вроде: _id:ObjectId()
Но зная, что Mongo автоматически назначит _id в случае отсутствия, вы можете использовать агрегат для создания $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'}
])