MongoDB rename database field within array

Andrew Samuelsen picture Andrew Samuelsen · Feb 3, 2012 · Viewed 19.9k times · Source

I need to rename indentifier in this:

{ "general" : 
  { "files" : 
    { "file" : 
      [  
        {  "version" : 
          {  "software_program" : "MonkeyPlus",      
             "indentifier" : "6.0.0" 
          } 
        } 
      ] 
    } 
  } 
}

I've tried

db.nrel.component.update(
  {},
  { $rename: {
    "general.files.file.$.version.indentifier" : "general.files.file.$.version.identifier"
  } },
  false, true
)

but it returns: $rename source may not be dynamic array.

Answer

Eli Gassert picture Eli Gassert · Sep 26, 2014

For what it's worth, while it sounds awful to have to do, the solution is actually pretty easy. This of course depends on how many records you have. But here's my example:

db.Setting.find({ 'Value.Tiers.0.AssetsUnderManagement': { $exists: 1 } }).snapshot().forEach(function(item)
{    
    for(i = 0; i != item.Value.Tiers.length; ++i)
    {
        item.Value.Tiers[i].Aum = item.Value.Tiers[i].AssetsUnderManagement;
        delete item.Value.Tiers[i].AssetsUnderManagement;
    }

    db.Setting.update({_id: item._id}, item);
});

I iterate over my collection where the array is found and the "wrong" name is found. I then iterate over the sub collection, set the new value, delete the old, and update the whole document. It was relatively painless. Granted I only have a few tens of thousands of rows to search through, of which only a few dozen meet the criteria.

Still, I hope this answer helps someone!

Edit: Added snapshot() to the query. See why in the comments.

You must apply snapshot() to the cursor before retrieving any documents from the database. You can only use snapshot() with unsharded collections.

From MongoDB 3.4, snapshot() function was removed. So if using Mongo 3.4+ ,the example above should remove snapshot() function.