简体   繁体   中英

Nested Query on Array in MongoDB collection

I have below User collection and I want find/update query to update nested array elements.

{
_id:"000-0000-0001",
Roles :{
         0000-0000-0011: //EngagementId
        ["0000-0000-0111", "0000-0000-0112", "0000-0000-3333"],//RoleId
         "0000-0000-0012" : 
        ["0000-0000-0121", "0000-0000-0112"]
       }
},
{

_id:"000-0000-0002",
Roles :{
         "0000-0000-0021" : [ "0000-0000-0222", "0000-0000-0112"],
         "0000-0000-0022" : [ "0000-0000-0121", "0000-0000-0112"],
         "0000-0000-0022" : [ "0000-0000-0121", "0000-0000-0112", "0000-0000-3333"]
       }
}

Requirement: I want to pull RoleId 0000-0000-3333 if the array have combination of 0000-0000-3333 and 0000-0000-0112

Below is expected result:

{
_id:"000-0000-0001",
Roles :{
         "0000-0000-0011" : ["0000-0000-0111", "0000-0000-0112"],
         "0000-0000-0012" : ["0000-0000-0121", "0000-0000-0112"]
       }
},
{

_id:"000-0000-0002"
Roles :{
         "0000-0000-0021" : [ "0000-0000-0222", "0000-0000-0112"],
         "0000-0000-0022" : [ "0000-0000-0121", "0000-0000-0112"],
         "0000-0000-0022" : [ "0000-0000-0121", "0000-0000-0112"]
       }
}

Note: Find/update will work on Key:value or if it is nested then key.key:value, but in above example we have key.value.[values]:$pull(value) and that's the challaenge.

The data model necessitates a complicated update with a pipeline.

Here' one way to do it.

db.collection.update({
  "Roles": {"$exists": true}
},
[
  {
    "$set": {
      "Roles": {
        "$arrayToObject": {
          "$map": {
            "input": {"$objectToArray": "$Roles"},
            "as": "roleKV",
            "in": {
              "k": "$$roleKV.k",
              "v": {
                "$cond": [
                  {
                    "$and": [
                      {"$in": ["0000-0000-0112", "$$roleKV.v"]},
                      {"$in": ["0000-0000-3333", "$$roleKV.v"]}
                    ]
                  },
                  {
                    "$filter": {
                      "input": "$$roleKV.v",
                      "cond": {"$ne": ["$$this", "0000-0000-3333"]}
                    }
                  },
                  "$$roleKV.v"
                ]
              }
            }
          }
        }
      }
    }
  }
],
{"multi": true}
)

Try it on mongoplayground.net .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM