1

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

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

new challenge if you have time : stackoverflow.com/questions/74337688/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.