Search code examples
mongodbmongoosemongodb-queryaggregate

$mergeObjects requires object inputs, but input is of type array


I am trying to add one property if current user has permission or not based on email exists in array of objects.

My input data looks like below.

[
  {
    nId: 0,
    children0: [
      {
        nId: 3,
        access: [
          {
            permission: "view",
            email: "user1@email.com"
          }
        ]
      },
      {
        nId: 4,
        access: [
          {
            permission: "view",
            email: "user2@email.com"
          }
        ]
      }
    ]
  }
]

https://mongoplayground.net/p/xZmRGFharAb

[
  {
    "$addFields": {
      "children0": {
        "$map": {
          "input": "$children0.access",
          "as": "accessInfo",
          "in": {
            "$cond": [
              {
                "$eq": [
                  "$$accessInfo.email",
                  "user1@email.com"
                ]
              },
              {
                "$mergeObjects": [
                  "$$accessInfo",
                  {
                    "hasAccess": true
                  }
                ]
              },
              {
                "$mergeObjects": [
                  "$$accessInfo",
                  {
                    "hasAccess": false
                  }
                ]
              },
              
            ]
          }
        }
      }
    }
  }
]

I also tried this answer as following, but that is also not merging the object.

https://mongoplayground.net/p/VNXcDnXl_sZ


Solution

  • Try this:

    db.collection.aggregate([
      {
        "$addFields": {
          "children0": {
            "$map": {
              "input": "$children0",
              "as": "accessInfo",
              "in": {
                nId: "$$accessInfo.nId",
                access: "$$accessInfo.access",
                hasAccess: {
                  "$cond": {
                    "if": {
                      "$ne": [
                        {
                          "$size": {
                            "$filter": {
                              "input": "$$accessInfo.access",
                              "as": "item",
                              "cond": {
                                "$eq": [
                                  "$$item.email",
                                  "user1@email.com"
                                ]
                              }
                            }
                          }
                        },
                        0
                      ]
                    },
                    "then": true,
                    "else": false
                  }
                }
              }
            }
          }
        }
      }
    ])
    

    Here, we use one $map to loop over children0 and then we filter the access array to contain only elements with matching emails. If the filtered array is non-empty, we set hasAccess to true.

    Playground link.