Home > OS >  Remove multiple objects from nested array 3
Remove multiple objects from nested array 3

Time:11-05

I try to clean my collection with single update query , need to remove some deeply nested objects , but without breaking other objects , here is a good solution provided by @rickhg12hs:

Remove multiple objects from deeply nested array 2

but it has small drawback , it is breaking the content of _a._p object when there is no _a._p.s object inside...

and original solution provided by @nimrod serok:

Remove multiple elements from deep nested array with single update query

but it has other issue , when there is missing "_a._p.s.c" , "_a._p.s.d" or "_a._p.s.a" object it add objects with null values instead which afcourse is not expected ...

Playground test

This are 2x example original documents:

[
{
"_id": ObjectId("5c05984246a0201286d4b57a"),
f: "x",
"_a": [
  {
    "_onlineStore": {}
  },
  {
    "_p": {
      "s": {
        "a": {
          "t": [
            {
              id: 1,
              "dateP": "20200-09-20",
              did: "x",
              dst: "y",
              den: "z"
            },
            {
              id: 2,
              "dateP": "20200-09-20"
            }
          ]
        },
        "c": {
          "t": [
            {
              id: 3,
              "dateP": "20300-09-22"
            },
            {
              id: 4,
              "dateP": "20300-09-23",
              did: "x",
              dst: "y",
              den: "z"
            },
            {
              id: 5,
              "dateP": "20300-09-23"
            }
          ]
        }
      }
    }
    }
   ]
 },
 {
"_id": ObjectId("5c05984246a0201286d4b57b"),
f: "x",
"_a": [
  {
    "_onlineStore": {}
  },
  {
    "_p": {
      _t: "Some field",
      _x: "Some other field"
    }
    }
  ]
 }
]

Expected result after update:

[
{
 "_a": [
  {
    "_onlineStore": {}
  },
  {
    "_p": {
      "s": {
        "a": {
          "t": [
            {
              "dateP": "20200-09-20",
              "den": "z",
              "did": "x",
              "dst": "y",
              "id": 1
            }
          ]
        },
        "c": {
          "t": [
            {
              "dateP": "20300-09-23",
              "den": "z",
              "did": "x",
              "dst": "y",
              "id": 4
            }
          ]
        }
      }
    }
  }
  ],
  "_id": ObjectId("5c05984246a0201286d4b57a"),
  "f": "x"
 },
 {
 "_a": [
  {
    "_onlineStore": {}
  },
  {
   "_p": {
      _t: "Some field",
      _x: "Some other field"
}
  }
],
"_id": ObjectId("5c05984246a0201286d4b57b"),
"f": "x"
}
]

The goal is with single update query to remove any objects under _a._p.s.[a|c|d].t where the fields did,dst and den are missing but without breaking other objects _a._p where _a._p.s do not exists ...

CodePudding user response:

Looks like a small change to @rickhg12hs's answer can solve this:

db.collection.update({},
[
  {$set: {
      _a: {$map: {
        input: "$_a",
        as: "elem",
        in: {$cond: [
              {$or: [
                {$eq: [{$type: "$$elem._p"}, "missing"]},
                {$eq: [{$type: "$$elem._p.s"}, "missing"]}
                ]},
              "$$elem",
              {
                _p: {s: {
                    $arrayToObject: {$map: {
                        input: {$objectToArray: "$$elem._p.s"},
                        as: "anyKey",
                        in: {
                          k: "$$anyKey.k",
                          v: {
                            t: {$filter: {
                                input: "$$anyKey.v.t",
                                as: "t",
                                cond: {$setIsSubset: [
                                    ["did", "dst", "den"],
                                    {$map: {
                                        input: {$objectToArray: "$$t"},
                                        in: "$$this.k"
                                    }}
                                ]}
                            }}
                          }
                        }
                    }}
                  }
              }}
          ]}
      }}
  }}
],
{
  "multi": true
})

See how it works on the playground example

  • Related