Home > Net >  Update name of a key in nested mongo document
Update name of a key in nested mongo document

Time:12-15

I did check on multiple platforms for the solution, however did not get the answer. Here is my problem:
I have a nested Mongo Document of the format:

{
    _id: "xxxx",
    "Type": <value>,
    "Data" : {
        "1": {                        <<< this key might differ for diff documents
            "00": {                   <<< this key might differ for diff documents
                 "cont": "India"
            },
            "05": {
                 "cont": "India"
            },
            ....
         }
         "32": {
            "41": {
                 "cont": "India"
            },
            "44": {
                 "cont": "India"
            },
            ....
        }
    }
}

I want to rename the key cont to country in all the documents in the collection, however as mentioned above the key 1, 00, 32 might differ for different documents hence I could not reach to a solution for this. Is there something like:

db.collection.updateMany({Type: "abc"}, { $rename: { "Data.*.*.cont": "Data.*.*.country" }})

because the key cont resides at the third level after the key Data

Can someone please help me out here?
Thanks!

CodePudding user response:

Using dynamic value as field name is generally considered as an anti-pattern. Nevertheless, you can still use $objectToArray to convert the nested objects into k-v tuples and manipulate them. Then converted it back using $arrayToObject

db.collection.update({},
[
  {
    "$addFields": {
      "arr": {
        // first conversion
        "$objectToArray": "$Data"
      }
    }
  },
  {
    "$addFields": {
      "arr": {
        // second conversion
        "$map": {
          "input": "$arr",
          "as": "a",
          "in": {
            k: "$$a.k",
            v: {
              "$objectToArray": "$$a.v"
            }
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "arr": {
        "$map": {
          "input": "$arr",
          "as": "a",
          "in": {
            k: "$$a.k",
            v: {
              "$map": {
                "input": "$$a.v",
                "as": "a2",
                "in": {
                  k: "$$a2.k",
                  // rename the field `country`
                  v: {
                    country: "$$a2.v.cont"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "arr": {
        "$map": {
          "input": "$arr",
          "as": "a",
          "in": {
            k: "$$a.k",
            v: {
              // 1st backward conversion
              "$arrayToObject": "$$a.v"
            }
          }
        }
      }
    }
  },
  {
    "$project": {
      _id: 1,
      Type: 1,
      "Data": {
        // 2nd backward conversion
        "$arrayToObject": "$arr"
      }
    }
  }
])

Here is the Mongo playground for your reference.

  • Related