MongoDB Single Update Query to Change the Field Name in All Matching Documents of the Collection

Including field name in nested object and array of objects.

Say we have a users collection in MongoDB with many existing documents. One example document from the collection:

{
  "_id": {
    "$oid": "650b0879d96098a3f57dc950"
  },
  "firstName": "John",
  "lastName": "Smith",
  "friends": [
    {
      "$oid": "650b0879d96098a3f57dc951"
    },
    {
      "$oid": "650b0879d96098a3f57dc952"
    },
    {
      "$oid": "650b0879d96098a3f57dc953"
    }
  ],
  "_spouse": {
    "$oid": "650b0879d96098a3f57dc954"
  },
  "address": {
    "street": "16133 E Foothill Blvd",
    "city": "Fontana",
    "Latitude": 34.106392,
    "Longitude": -117.452627
  },
  "images": [
    {
      "id": 1,
      "ur": "https://dummyimage.com/700x300/000/fff"
    },
    {
      "id": 2,
      "ur": "https://dummyimage.com/700x400/000/fff"
    }
  ],
  "Active": true
}

Here, we have a couple of fields and nested fields, which we like to change because of mistakes or better naming conventions such as Address to address, _spouse to spouse, Latitude/Longitude inside the address to latitude/longitude and ur inside the image object to url.

We’ll use updateMany query with aggregation pipeline (with [...]) to update all these field names (or keys).

Below, here’s how we can do that:

Change Field Name

To fix single field Active:

db.users.updateMany(
  { Active: { $exists: true } },
  [{ $set: { active: "$Active" } }, { $unset: "Active" }]
)

Note the $ sign before the current field name Active during the $set operation. It reads the current value of the existing field.

To update multiple fields at once:

db.users.updateMany(
  { Active: { $exists: true }, _spouse: { $exists: true } },
  [
    { $set: { active: "$Active", spouse: "$_spouse" } },
    { $unset: ["Active", "_spouse"] }
  ]
)

Note that we use an array of field names to unset the old fields.

Be very careful to ensure the field to be renamed exists in the collection before copying and removing it. Passing empty {} and running the update query mistakenly twice will wipe out the previous and new fields.

Change Nested Object Field Name

Let’s fix Latitude and Longitude inside the address object.

db.users.updateMany(
  { "address.Latitude": { $exists: true }, "address.Longitude": { $exists: true } },
  [
    {
      $set:
        { "address.latitude": "$address.Latitude", "address.longitude": "$address.Longitude" }
    },
    {
      $unset: ["address.Latitude", "address.Longitude"]
    }
  ]
)

Change Object Field Name Inside Array

The images contains objects containing id and ur. As ur is misspelled, we want to rename it to url. This will be done slightly differently using $map operator, in which we replace each images element with a new object after making the conditional modification (copy ur value to url if it exists else, keep the url value as is).

db.users.updateMany(
  {},
  [{
  $set: {
    "images": {
      $map: {
        input: "$images",
        as: "image",
        in: {
          id: "$$image.id",
          ur: "https://google.com",
          url: {
            $cond: { if: { "$$image.ur": { $exists: true } }, then: "google", else: "yahoo" }
          }

        }
      }
    }
  }
}]
)

The same query will work with slight modifications for changing the nested object field name within an array.

Convert Array Field to Non-array Field and Rename It

Here’s an example document from the examples collection:

{
  "_id": {
    "$oid": "650b0b7ed96098a3f57dc953"
  },
  "customers" ["123"]
}

We want to rename customers to customer and copy its first (and only) element to customer. Here’s how we do it:

db.examples.updateMany(
  { "customers": { $exists: true } },
  [
    {
      $set: {
        customer: { $arrayElemAt: ["$customers", 0] },
      },
    },
    {
      $unset: "customers",
    },
  ]
)



See also

When you purchase through links on techighness.com, I may earn an affiliate commission.