296

Assuming I have a collection in MongoDB with 5000 records, each containing something similar to:

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

Is there an easy way to rename the field "additional" to "last" in all documents? I saw the $rename operator in the documentation but I'm not really clear on how to specify a subfield.

felipsmartins
  • 13,269
  • 4
  • 48
  • 56
soulkphp
  • 3,753
  • 2
  • 17
  • 14

7 Answers7

533

You can use:

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

Or to just update the docs which contain the property:

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

The false, true in the method above are: { upsert:false, multi:true }. You need the multi:true to update all your records.

Or you can use the former way:

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

In MongoDB 3.2 you can also use

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

The general syntax of this is

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

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

Mr.Singh
  • 1,421
  • 6
  • 21
  • 46
Felix Yan
  • 14,841
  • 7
  • 48
  • 61
  • 60
    Just a word for if you are banging your head against the wall because nothing is mass updated: the `false, true` in the `update` method of the `$rename` version are: `{ upsert:false, multi:true }`. You need the `multi:true` to update all your records. – RickyA Mar 07 '13 at 14:29
  • 1
    and if I'm getting it `upsert:true` will create field name if field name does not exists, defaults to `false`. – IGRACH Jan 01 '15 at 21:43
  • 1
    For some reason, this didn't work for me when I used the `"table.field" : "table.field"` syntax. It did work when I just used the `"field" : "field"` syntax. – Ben Sep 02 '15 at 00:21
  • @Steve `name.last` is not `table.field`. If you read the question, you can see that the `name` field holds an object. – Marc Dingena Oct 01 '15 at 08:31
  • Is this working with arrays as well? Can I do: `db.foo.update({}, {$rename:{"name.0.additional":"name.0.last"}}, false, true)`? – bncc May 24 '16 at 08:16
  • For future generations. this also works in form {'fieldName': 'subDocument.fieldName'} – Čamo Sep 08 '18 at 15:58
  • perfect, for me I have to write as Model.collection.updateMany(filterObject, {$rename:{ : }}) I'm running mongoose version 3.2.7 may be because of versioning. Thank You – Yash Parekh Oct 26 '20 at 17:54
  • `db.parks.update({}, {$rename:{"pipe":"location"}}, false, true);` this doesnj't work for me. – chovy Dec 02 '22 at 19:13
68

You can use the $rename field update operator:

db.collection.update(
  {},
  { $rename: { 'name.additional': 'name.last' } },
  { multi: true }
)
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
Alex
  • 681
  • 5
  • 3
  • 2
    According to the new documentation, it should look like: db.collectionName.updateMany({}, { $rename : { 'name.additional' : 'name.last' } } ) – 1r3k Oct 20 '16 at 09:31
  • 1
    @1r3k this is old but to help others avoid confusion, no, `updateMany` is a Mongoose command, not a MongoDB command. that command won't work. – ChumiestBucket Apr 09 '21 at 17:25
  • 1
    @ChumiestBucket no, this is correct. UpdateMany is a mongodb command. See here: https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/ – 1r3k Apr 10 '21 at 19:08
15

If ever you need to do the same thing with mongoid:

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

UPDATE

There is change in the syntax in monogoid 4.0.0:

Model.all.rename(old_field: :new_field)
cortex
  • 5,036
  • 3
  • 31
  • 41
magicgregz
  • 7,471
  • 3
  • 35
  • 27
4

Anyone could potentially use this command to rename a field from the collection (By not using any _id):

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

see FYI

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Mahan
  • 371
  • 1
  • 4
  • 11
1

I am using ,Mongo 3.4.0

The $rename operator updates the name of a field and has the following form:

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

for e.g

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

The new field name must differ from the existing field name. To specify a in an embedded document, use dot notation.

This operation renames the field nmae to name for all documents in the collection:

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

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

In the method above false, true are: { upsert:false, multi:true }.To update all your records, You need the multi:true.

Rename a Field in an Embedded Document

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

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

Swadeshi
  • 1,596
  • 21
  • 33
0

This nodejs code just do that , as @Felix Yan mentioned former way seems to work just fine , i had some issues with other snipets hope this helps.

This will rename column "oldColumnName" to be "newColumnName" of table "documents"

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

// Connection URL
//var url = 'mongodb://localhost:27017/myproject';
var url = 'mongodb://myuser:mypwd@myserver.cloud.com: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
  • 7,497
  • 1
  • 51
  • 37
0

If you are using MongoMapper, this works:

Access.collection.update( {}, { '$rename' => { 'location' => 'location_info' } }, :multi => true )
Jon Kern
  • 3,186
  • 32
  • 34