Changing keys inside array of objects of document

Hi there everyone

Can someone that knows of mongodb aggregation pipeline stages help me? It’s a simple thing, but I’m just a noob and I haven’t found a solution in my searches: I need to transform the “_id” key to “id” of the objects inside an array of a document. So, I need to make this:

{
            "reviews": [
                {
                    "_id": "61e412003c043e620a4ca97d"
                },
                {
                    "_id": "61e412153c043e620a4ca983"
                },
                {
                    "_id": "61e4127c3c043e620a4ca989"
                }
            ],
            "id": "61e411be3c043e620a4ca979"
}

Become this:

{
            "reviews": [
                {
                    "id": "61e412003c043e620a4ca97d"
                },
                {
                    "id": "61e412153c043e620a4ca983"
                },
                {
                    "id": "61e4127c3c043e620a4ca989"
                }
            ],
            "id": "61e411be3c043e620a4ca979"
}

I managed to do this with two pipeline stages: addFields (to add id) → project (to remove _id) with this input for $addFields operator :

{
  id: "$_id",
  reviews: { 
    $map: 
      { 
        input: "$reviews", 
        as: "review", 
        in: { 
          $setField: { 
              field: "id",
              input: "$$review",
              value: "$$review._id"
          } 
        }
      }
  }
}

It did the trick, but my production mongodb version, 4.4.11, doesn’t recognize the $setField operator and it’s currently breaking because of that

Is there a simple alternative to do this?

1 Like

I was able to find something that works but in 2 passes.

First pass uses aggregation to copy the field _id into id.

map = { '$map' : { 'input' : '$reviews' , 'in' : { '$mergeObjects' : [ "$$this" , { 'id' : '$$this._id'}] } } }
update = { '$set' : { 'reviews' : map } }
merge = {  '$merge' : 'Collection_Name' }
db.Collection_Name.aggregate( [ update , marge ] )

The second pass uses $unset on updateMany:

db.Collection_Name.updateMany( { 'reviews._id' : { '$exists' : true } } ,{ "$unset" : { "reviews.$[]._id" : true }})

Personally, I get lost with too many ids. I like to prefix them. Something like user_id, review_id. Searching for the string id in a big project can be tedious.