skip to Main Content

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?

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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"
                }
              }
            }
          }
        }
      }
    ])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search