У меня есть коллекция t1
со следующими полями в ее схеме
_id, field1, field1
Я хочу установить field2
значение field1
как sql:
update t1 set field1=field2;
Как мне это сделать в MongoDB?
У меня есть коллекция t1
со следующими полями в ее схеме
_id, field1, field1
Я хочу установить field2
значение field1
как sql:
update t1 set field1=field2;
Как мне это сделать в MongoDB?
Здесь хорошие и плохие новости.
Плохая новость заключается в том, что AFAIK вы не можете сделать это с помощью одного вызова update() - mongo не поддерживает обращение к текущему объекту в обновлении.
Хорошая новость заключается в том, что есть другие способы сделать это, например. вы можете запустить цикл forEach:
db.item.find(conditions...).forEach( function (doc) {
doc.field1 = doc.field2;
db.item.save(doc);
});
Вы можете запускать forEach в оболочке администратора (команда "mongo" ) или с помощью некоторых методов вашего конкретного драйвера (например, в PHP, я ожидаю, что он будет работать с mongodb.execute(), как описано здесь: http://www.php.net/manual/en/mongodb.execute.php)
Начиная с версии 3.4, мы можем использовать оператор конвейера агрегации $addFields
для этого без обработки на стороне клиента, что является наиболее эффективным способом.
db.collection.aggregate(
[
{ "$addFields": { "field2": "$field1" }},
{ "$out": "collection" }
]
)
До версии 3.4 нам нужно выполнить итерацию объекта Cursor
и использовать $set
, чтобы добавить новое поле с существующим Значение "field1". Для максимальной эффективности вам нужно сделать это, используя "объемную" операцию.
MongoDB 3.2 обесценивает Bulk()
и связанные методы,, таким образом, с 3.2 вверх вы должны использовать метод bulkWrite
.
var requests = [];
db.collection.find({}, { 'field1': 1 } ).snapshot().forEach(document => {
requests.push( {
'updateOne': {
'filter': { '_id': document._id },
'update': { '$set': { 'field2': document.field1 } }
}
});
if (requests.length === 1000) {
//Execute per 1000 operations and re-init
db.collection.bulkWrite(requests);
requests = [];
}
});
if(requests.length > 0) {
db.collection.bulkWrite(requests);
}
От версии 2.6 до 3.0 вы можете использовать API Bulk
.
var bulk = db.collection.initializeUnorderedBulOp();
var count = 0;
db.collection.find({}, { 'field1': 1 }).snapshot().forEach(function(document) {
bulk.find({ '_id': document._id }).updateOne( {
'$set': { 'field2': document.field1 }
});
count++;
if(count%1000 === 0) {
// Excecute per 1000 operations and re-init
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// clean up queues
if(count > 0) {
bulk.execute();
}
Это можно сделать с помощью:
db.nameOfCollection.find().forEach(
function (elem) {
db.nameOfCollection.update(
{
_id: elem._id
},
{
$set: {
field2: elem.field1
}
}
);
}
);