skip to Main Content

I have the following record:

id: 119,
customfields: Array (2)

  0: Object
    value: "Mr"
    type: "salutation"

  1: Object
    value: "Google"
    type: "company"

I need to update this document so that I get:


id: 119,
salutation: "Mr",
company: "Google"

Important is:

  • The position of the arguments can vary, ie, some records have salutation first, others have company and other may have other fields that do not matter.
  • some documents do not have the salutation records inside the customfields array and therefore should just be ignored. Same logic for the company.

2

Answers


  1. $map customfields to an array of k-v tuple first. Then, $mergeObjects with $$ROOT object to get the final object. $unset the now useless customfields and $merge by id to update back to the document.

    db.collection.aggregate([
      {
        "$match": {
          "id": 119
        }
      },
      {
        "$set": {
          "customfields": {
            "$arrayToObject": {
              "$map": {
                "input": "$customfields",
                "as": "cf",
                "in": {
                  "k": "$$cf.type",
                  "v": "$$cf.value"
                }
              }
            }
          }
        }
      },
      {
        "$replaceRoot": {
          "newRoot": {
            "$mergeObjects": [
              "$$ROOT",
              "$customfields"
            ]
          }
        }
      },
      {
        "$unset": "customfields"
      },
      {
        "$merge": {
          "into": "collection",
          "on": "id"
        }
      }
    ])
    

    Mongo Playground

    Login or Signup to reply.
  2. Here’s another way to do it using "$reduce" to rebuild the document.

    db.collection.update({
      "id": 119
    },
    [
      {
        "$set": {
          "newRoot": {
            "$reduce": {
              "input": "$customfields",
              "initialValue": {
                "id": "$id"
              },
              "in": {
                "$mergeObjects": [
                  "$$value",
                  {
                    "$arrayToObject": [
                      [
                        {
                          "k": "$$this.type",
                          "v": "$$this.value"
                        }
                      ]
                    ]
                  }
                ]
              }
            }
          }
        }
      },
      {"$replaceWith": "$newRoot"}
    ])
    

    Try it on mongoplayground.net.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search