Como posso renomear um campo para todos os documentos no MongoDB?

223

Supondo que eu tenha uma coleção no MongoDB com 5000 registros, cada um contendo algo semelhante a:

{
"occupation":"Doctor",
"name": {
   "first":"Jimmy",
   "additional":"Smith"
}

Existe uma maneira fácil de renomear o campo "adicional" para "último" em todos os documentos? Eu vi o operador $ rename na documentação, mas não sou muito claro sobre como especificar um subcampo.

soulkphp
fonte

Respostas:

423

Você pode usar:

db.foo.update({}, {$rename:{"name.additional":"name.last"}}, false, true);

Ou apenas atualize os documentos que contêm a propriedade:

db.foo.update({"name.additional": {$exists: true}}, {$rename:{"name.additional":"name.last"}}, false, true);

A false, trueno método acima são os seguintes: { upsert:false, multi:true }. Você precisa multi:trueatualizar todos os seus registros.

Ou você pode usar da maneira anterior:

remap = function (x) {
  if (x.additional){
    db.foo.update({_id:x._id}, {$set:{"name.last":x.name.additional}, $unset:{"name.additional":1}});
  }
}

db.foo.find().forEach(remap);

No MongoDB 3.2, você também pode usar

db.students.updateMany( {}, { $rename: { "oldname": "newname" } } )

A sintaxe geral disso é

db.collection.updateMany(filter, update, options)

https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/

Felix Yan
fonte
52
Apenas uma palavra para se você está batendo sua cabeça contra a parede porque nada é massa atualização: o false, trueno updatemétodo da $renameversão são: { upsert:false, multi:true }. Você precisa multi:trueatualizar todos os seus registros.
precisa saber é o seguinte
1
e se estiver obtendo, ele upsert:truecriará o nome do campo se o nome do campo não existir, o padrão será false.
IGRACH 01/01
1
Por alguma razão, isso não funcionou para mim quando usei a "table.field" : "table.field"sintaxe. Funcionou quando eu apenas usei a "field" : "field"sintaxe.
Ben
@ Steve name.lastnão é table.field. Se você ler a pergunta, poderá ver que o namecampo contém um objeto.
Marc Dingena
Isso também funciona com matrizes? Posso fazer db.foo.update({}, {$rename:{"name.0.additional":"name.0.last"}}, false, true):?
bncc 24/05
49

tente por favor db.collectionName.update({}, { $rename : { 'name.additional' : 'name.last' } }, { multi: true } )

e leia isto :) http://docs.mongodb.org/manual/reference/operator/rename/#_S_rename

Alex
fonte
1
Atualize o link, parece que a nova documentação não diz nada sobre as opções upserte multi.
Akos K
1
De acordo com a nova documentação, ele deve se parecer com: db.collectionName.updateMany ({}, {$ rename: {'name.additional': 'name.last'}})
1r3k 20/10/16
15

Se alguma vez você precisar fazer a mesma coisa com o mongoid:

Model.all.rename(:old_field, :new_field)

ATUALIZAR

Há alterações na sintaxe em monogoid 4.0.0:

Model.all.rename(old_field: :new_field)
metakungfu
fonte
11
Houve alteração na sintaxe no último monogoid (4.0.0)Model.all.rename(old_field: :new_field)
Calin
Como posso usar esta opção para o documento
incorporado
2

Qualquer pessoa poderia usar esse comando para renomear um campo da coleção (não usando _id):

dbName.collectionName.update({}, {$rename:{"oldFieldName":"newFieldName"}}, false, true);

veja FYI

Mants
fonte
0

Este código nodejs apenas faz isso, como o @Felix Yan mencionou o modo antigo parece funcionar muito bem, eu tive alguns problemas com outros snipets, espero que isso ajude.

Isso renomeará a coluna "oldColumnName" como "newColumnName" da tabela "documentos"

var MongoClient = require('mongodb').MongoClient
  , assert = require('assert');

// Connection URL
//var url = 'mongodb://localhost:27017/myproject';
var url = 'mongodb://myuser:[email protected]:portNumber/databasename';

// Use connect method to connect to the server
MongoClient.connect(url, function(err, db) {
  assert.equal(null, err);
  console.log("Connected successfully to server");

  renameDBColumn(db, function() {
    db.close();
  });

});

//
// This function should be used for renaming a field for all documents
//
var renameDBColumn = function(db, callback) {
  // Get the documents collection
  console.log("renaming database column of table documents");
  //use the former way:
  remap = function (x) {
    if (x.oldColumnName){
      db.collection('documents').update({_id:x._id}, {$set:{"newColumnName":x.oldColumnName}, $unset:{"oldColumnName":1}});
    }
  }

  db.collection('documents').find().forEach(remap);
  console.log("db table documents remap successfully!");
}
d1jhoni1b
fonte
0

Eu estou usando, Mongo 3.4.0

O operador $ rename atualiza o nome de um campo e tem o seguinte formato:

{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }

por exemplo

db.getCollection('user').update( { _id: 1 }, { $rename: { 'fname': 'FirstName', 'lname': 'LastName' } } )

O novo nome do campo deve ser diferente do nome do campo existente. Para especificar a em um documento incorporado, use a notação de ponto.

Esta operação renomeia o campo nmae para nomear todos os documentos da coleção:

db.getCollection('user').updateMany( {}, { $rename: { "add": "Address" } } )

db.getCollection('user').update({}, {$rename:{"name.first":"name.FirstName"}}, false, true);

No método acima false, true são: {upsert: false, multi: true}. Para atualizar todos os seus registros, você precisa do multi: true.

Renomear um campo em um documento incorporado

db.getCollection('user').update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )

use o link: https://docs.mongodb.com/manual/reference/operator/update/rename/

Swadeshi
fonte
A opção de incorporação não está funcionando ... Eu recebo este erro "não pode usar a parte (endereço do address.city) para atravessar o elemento"
Huzaifa Saifuddin
0

Se você estiver usando o MongoMapper, isso funcionará:

Access.collection.update( {}, { '$rename' => { 'location' => 'location_info' } }, :multi => true )
Jon Kern
fonte