Comment renommer un champ pour tous les documents dans MongoDB?

223

En supposant que j'ai une collection dans MongoDB avec 5000 enregistrements, chacun contenant quelque chose de similaire à:

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

Existe-t-il un moyen simple de renommer le champ "supplémentaire" en "dernier" dans tous les documents? J'ai vu l' opérateur $ rename dans la documentation mais je ne sais pas vraiment comment spécifier un sous-champ.

soulkphp
la source

Réponses:

423

Vous pouvez utiliser:

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

Ou pour simplement mettre à jour les documents qui contiennent la propriété:

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

Le false, truedessus dans le procédé sont les suivants : { upsert:false, multi:true }. Vous devez multi:truemettre à jour tous vos enregistrements.

Ou vous pouvez utiliser l'ancienne méthode:

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);

Dans MongoDB 3.2, vous pouvez également utiliser

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

La syntaxe générale de ceci est

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

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

Felix Yan
la source
52
Juste un mot pour si vous cogner la tête contre le mur parce que rien est mis à jour en masse: la false, truedans la updateméthode de la $renameversion sont: { upsert:false, multi:true }. Vous devez multi:truemettre à jour tous vos enregistrements.
RickyA
1
et si j'obtiens, il upsert:truecréera un nom de champ si le nom de champ n'existe pas, par défaut à false.
IGRACH
1
Pour une raison quelconque, cela n'a pas fonctionné pour moi lorsque j'ai utilisé la "table.field" : "table.field"syntaxe. Cela a fonctionné lorsque je viens d'utiliser la "field" : "field"syntaxe.
Ben
@Steve name.lastne l'est pas table.field. Si vous lisez la question, vous pouvez voir que le namechamp contient un objet.
Marc Dingena
Cela fonctionne-t-il également avec les tableaux? Puis-je faire db.foo.update({}, {$rename:{"name.0.additional":"name.0.last"}}, false, true):?
bncc
49

s'il vous plaît essayez db.collectionName.update({}, { $rename : { 'name.additional' : 'name.last' } }, { multi: true } )

et lisez ceci :) http://docs.mongodb.org/manual/reference/operator/rename/#_S_rename

Alex
la source
1
Veuillez mettre à jour le lien, la nouvelle documentation ne dit rien sur les options upsertet multi.
Akos K
1
Selon la nouvelle documentation, elle devrait ressembler à: db.collectionName.updateMany ({}, {$ rename: {'name.additional': 'name.last'}})
1r3k
15

Si jamais vous devez faire la même chose avec mongoid:

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

METTRE À JOUR

Il y a un changement dans la syntaxe dans monogoid 4.0.0:

Model.all.rename(old_field: :new_field)
metakungfu
la source
11
Il y a un changement de syntaxe dans le dernier monogoïde (4.0.0)Model.all.rename(old_field: :new_field)
Calin
Comment puis-je utiliser cette option pour un document
intégré
2

N'importe qui pourrait potentiellement utiliser cette commande pour renommer un champ de la collection (en n'utilisant aucun _id):

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

voir FYI

Mants
la source
0

Ce code nodejs fait juste cela, comme @Felix Yan a mentionné que l'ancienne méthode semble fonctionner très bien, j'ai eu quelques problèmes avec d'autres snipets, espérons que cela aidera.

Cela renommera la colonne "oldColumnName" en "newColumnName" de la table "documents"

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
la source
0

J'utilise Mongo 3.4.0

L'opérateur $ rename met à jour le nom d'un champ et a la forme suivante:

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

par exemple

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

Le nouveau nom de champ doit être différent du nom de champ existant. Pour spécifier un dans un document incorporé, utilisez la notation par points.

Cette opération renomme le champ nmae à nommer pour tous les documents de la collection:

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

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

Dans la méthode ci-dessus false, true sont: {upsert: false, multi: true}. Pour mettre à jour tous vos enregistrements, vous avez besoin du multi: true.

Renommer un champ dans un document incorporé

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

utilisez le lien: https://docs.mongodb.com/manual/reference/operator/update/rename/

Swadeshi
la source
L'option d'intégration ne fonctionne pas ... Je reçois cette erreur "ne peut pas utiliser la partie (adresse de address.city) pour traverser l'élément"
Huzaifa Saifuddin
0

Si vous utilisez MongoMapper, cela fonctionne:

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