¿Cómo puedo cambiar el nombre de un campo para todos los documentos en MongoDB?

223

Suponiendo que tengo una colección en MongoDB con 5000 registros, cada uno con algo similar a:

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

¿Hay una manera fácil de cambiar el nombre del campo "adicional" a "último" en todos los documentos? Vi el operador $ rename en la documentación, pero no tengo muy claro cómo especificar un subcampo.

soulkphp
fuente

Respuestas:

423

Puedes usar:

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

O simplemente para actualizar los documentos que contienen la propiedad:

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

El false, trueen el método anterior son: { upsert:false, multi:true }. Necesita multi:trueactualizar todos sus registros.

O puede usar la forma 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);

En MongoDB 3.2 también puedes usar

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

La sintaxis general de esto es

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

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

Felix Yan
fuente
52
Sólo una palabra de si va a golpearse la cabeza contra la pared porque nada se actualiza en masa: el false, trueen el updatemétodo de la $renameversión son: { upsert:false, multi:true }. Necesita multi:trueactualizar todos sus registros.
RickyA
1
y si lo obtengo upsert:truecreará el nombre del campo si el nombre del campo no existe, por defecto es false.
IGRACH 01 de
1
Por alguna razón, esto no funcionó para mí cuando usé la "table.field" : "table.field"sintaxis. Funcionó cuando acabo de usar la "field" : "field"sintaxis.
Ben
@ Steve name.lastno lo es table.field. Si lees la pregunta, puedes ver que el namecampo contiene un objeto.
Marc Dingena
¿Funciona esto también con matrices? ¿Puedo hacer: db.foo.update({}, {$rename:{"name.0.additional":"name.0.last"}}, false, true)?
bncc
49

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

y lee esto :) http://docs.mongodb.org/manual/reference/operator/rename/#_S_rename

Alex
fuente
1
Actualice el enlace, parece que la nueva documentación no dice nada sobre las opciones upserty multi.
Akos K
1
De acuerdo con la nueva documentación, debería verse así: db.collectionName.updateMany ({}, {$ rename: {'name.additional': 'name.last'}})
1r3k
15

Si alguna vez necesitas hacer lo mismo con mongoid:

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

ACTUALIZAR

Hay un cambio en la sintaxis en monogoid 4.0.0:

Model.all.rename(old_field: :new_field)
metakungfu
fuente
11
Hay un cambio en la sintaxis en el último monogoide (4.0.0)Model.all.rename(old_field: :new_field)
Calin
¿Cómo puedo usar esta opción para el documento
incorporado?
2

Cualquiera podría usar este comando para cambiar el nombre de un campo de la colección (al no usar ningún _id):

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

ver FYI

Mants
fuente
0

Este código de nodejs solo hace eso, como @Felix Yan mencionó que la forma anterior parece funcionar bien, tuve algunos problemas con otros fragmentos, espero que esto ayude.

Esto cambiará el nombre de la columna "oldColumnName" por "newColumnName" de la tabla "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
fuente
0

Estoy usando Mongo 3.4.0

El operador $ rename actualiza el nombre de un campo y tiene la siguiente forma:

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

por ej.

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

El nuevo nombre de campo debe diferir del nombre de campo existente. Para especificar un en un documento incrustado, use la notación de puntos.

Esta operación cambia el nombre del campo nmae para nombrar todos los documentos de la colección:

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

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

En el método anterior, falso, verdadero son: {upsert: falso, multi: verdadero}. Para actualizar todos sus registros, necesita el multi: verdadero.

Cambiar el nombre de un campo en un documento incrustado

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

utilice el enlace: https://docs.mongodb.com/manual/reference/operator/update/rename/

Swadeshi
fuente
La opción de incrustación no funciona ... Obtengo este error "no se puede usar la parte (dirección de address.city) para atravesar el elemento"
Huzaifa Saifuddin
0

Si está utilizando MongoMapper, esto funciona:

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