Home > Software design >  Is there any substitute of $arrayToObject in MongoDb
Is there any substitute of $arrayToObject in MongoDb

Time:04-29

I have a requirment of inverting an object keys & values. I have following type of data:

[
        "elements": {
            "title": "elem_1_6_title",
            "sub_title": "elem_1_6_sub_title",
            "media": "elem_1_6_media",
            "button": "elem_1_6_button",
            "give_us_call": "elem_1_6_give_us_call"
        },
        "elements": {
            "title": "elem_1_6_title",
            "sub_title": "elem_1_6_sub_title"
        },
        "elements": {}
    ]

Expected output:

[
    "elements": {
        "elem_1_6_title": "title",
        "elem_1_6_sub_title": "sub_title",
        "elem_1_6_media": "media",
        "elem_1_6_button": "button",
        "elem_1_6_give_us_call": "give_us_call"
    },
    "elements": {
        "elem_1_6_title": "title",
        "elem_1_6_sub_title": "sub_title"
    },
    "elements": {}
]

Pipeline:

[
    {
        "$addFields": {
            "sec_elems_arr": {
                "$objectToArray": "$elements"
            }
        }
    },
    {
        "$unwind": {
            "path": "$sec_elems_arr",
            "preserveNullAndEmptyArrays": true
        }
    },
    {
        "$addFields": {
            "section_elements": {
                "$arrayToObject": [
                    [
                        {
                            "k": "$sec_elems_arr.v",
                            "v": "$sec_elems_arr.k"
                        }
                    ]
                ]
            }
        }
    }
]

The above pipeline throws error:

 $arrayToObject requires an object keys of 'k' and 'v'. Found incorrect number of keys:0

because one of the above elements object have no key values. But this case can exist in the data. How can I achieve this using MongoDB aggregation pipeline?

CodePudding user response:

I think the problem is more about you are using the $arrayToObject incorrectly. You can use it with $map to correctly swap the k-v.

db.collection.aggregate([
  {
    $addFields: {
      elements: {
        "$objectToArray": "$elements"
      }
    }
  },
  {
    "$addFields": {
      "elements": {
        "$arrayToObject": {
          "$map": {
            "input": "$elements",
            "as": "e",
            "in": {
              k: "$$e.v",
              v: "$$e.k"
            }
          }
        }
      }
    }
  }
])

Here is the Mongo playground for your reference.

CodePudding user response:

Note the answer above can be further optimized by calling $objectToArray as the input to $map. This saves a stage -- always a good thing.

db.collection.aggregate([
  {
    "$addFields": {
      "elements": {
        "$arrayToObject": {
          "$map": {
            "input": {"$objectToArray": "$elements"},
            "as": "e",
            "in": {
              k: "$$e.v",
              v: "$$e.k"
            }
          }
        }
      }
    }
  }
])
  • Related