W Si
W Si

Reputation: 133

How to apply the "arrayFilters" on the top-level array?

My question is similar to Remove Object from Nested Array by Multiple Criteria. The major difference is that I want to apply the arrayFilter on the top-level array first and then apply another arrayFilter on the nested array of the matched top-level array element.

First of all, here is the document sample I copied over from the post with some adjustments to suit my case...

{
    "OtherField1" : ISODate("2016-05-06T05:09:14.589Z"),
    "OtherField2" : "something",
    "Distributions" : [
            {
                    "DeliveryType" : 1,
                    "DeliverySubType" : 2,
                    "DistributionData" : [
                            {
                                    "Key" : "Topic",
                                    "Value" : "Topics",
                                    "Children" : null
                            },
                            {
                                    "Key" : "Message",
                                    "Value" : "test",
                                    "Children" : null
                            }
                    ]
            },
            {
                    "DeliveryType" : 1,
                    "DeliverySubType" : 3,
                    "DistributionData" : [
                            {
                                    "Key" : "Topic",
                                    "Value" : "Topics",
                                    "Children" : ""
                            },
                            {
                                    "Key" : "Message",
                                    "Value" : "test",
                                    "Children" : null
                            }
                    ]
            }
    ]
}

What I want to achieve is to, first of all, locate the 2nd element of the top-level Distributions array by matching "DeliveryType" : 1 and "DeliverySubType" : 3, and then locate the 1st element of its nested DistributionData array by matching "Key": "Topic" and "Value" : "Topics", and finally update the Children field of matched nested array element.

For the top-level match, I tried the following forms ...

{
  "arrayFilters": [
  { "filter1" : {
      "elemMatch" : {
         "DeliveryType" : 1,
         "DeliverySubType" : 3,
       }
     }
  }
}

and referenced the filter as Distributions.$[filter1]..., but it didn't work. Or,

{
  "arrayFilters": [
  { "filter1.Distributions" : {
      "elemMatch" : {
         "DeliveryType" : 1,
         "DeliverySubType" : 3,
       }
     }
  }
}

and referenced the filter as $[filter1].Distributions...., but once again it failed with a parsing error.

All the examples I can found are about using the arrayFilters on the nested arrays and myself had some success in that regard, but no matter how hard I tried to apply the same tricks to the filters on the top-level array, they just failed with all sorts of errors. Could anyone help please? Thanks.

Upvotes: 3

Views: 1612

Answers (1)

dnickless
dnickless

Reputation: 10918

The solution is somewhat hidden but it's actually documented:

db.collection.update({}, {
    $set: { "Distributions.$[distFilter].DistributionData.$[distDataFilter].Children": "new value" }
    }, {
    "arrayFilters": [
        {
            "distFilter.DeliveryType" : 1,
            "distFilter.DeliverySubType" : 3
        }, {
            "distDataFilter.Key" : "Topic",
            "distDataFilter.Value" : "Topics"
        }
    ]
})

Upvotes: 5

Related Questions