Using MongoDB > v3.6 you can use the "all positional operator" $[] to achieve that:
db.collection.update({}, { $pull: { "Tests.$[].Data": { "Fact": "1" } } })
UPDATE in response to your comment:
If you want to pull all matching instances from the first matching entry in the Tests
array then this can be done like so:
db.collection.update({"Tests.Data": { $elemMatch: { "Fact": "1" } } }, { $pull: { "Tests.$.Data": { "Fact": "1" } } })
Let's look at the following example document:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "A"
{ 'Fact': '1' }, // second matching entry in "A"
{ 'Fact': '2' },
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "B"
{ 'Fact': '1' }, // second matching entry in "B"
{ 'Fact': '2' },
]
}
]
}
Running the above query once will give you this:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in "B"
{ 'Fact': '1' }, // second matching entry in "B"
{ 'Fact': '2' }
]
}
]
}
Running this a second time will wipe out all instances from "B"
, too.
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// all matching items gone from "B"
{ 'Fact': '2' }
]
}
]
}
If, however, you want to update only the very first matching instance inside the first matching entry in the Tests
array then I do not think this can be done in a single operation. However, here's a bit of a hack that appears to work:
db.collection.update({"Tests.Data": { $elemMatch: { "Fact": "1" } } }, { $set: { "Tests.$.Data.0": { "delete_me": 1 } } }) // this will set the first found { Fact: "1" } document inside the Tests.Data arrays to { delete_me: 1 }
db.collection.update({}, { $pull: { "Tests.$[].Data": { "delete_me": 1 } } }) // this will just delete the marked records from all arrays
Running this query once will yield this:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// first matching item gone from "A"
{ 'Fact': '1' }, // second matching entry in "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in Name "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
The next time you run this, again, another entry will be deleted:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
{ 'Fact': '1' }, // first matching entry in Name "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
Third run:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// first matching item gone from "B"
{ 'Fact': '1' }, // second matching entry in Name "B"
{ 'Fact': '2' }
]
}
]
}
And finally, fourth run:
{
"Tests" : [
{
"Name" : "A",
"Data" : [
// all matching items gone from "A"
{ 'Fact': '2' }
]
},
{
"Name" : "B",
"Data" : [
// all matching items gone from "B"
{ 'Fact': '2' }
]
}
]
}