I have a case where I want to query a collection of documents that have a number of items under a array field "forms". The problem to solve was wanting to return only the documents that have all of the documents contained in "forms" with a particular status of "closed".
So here is a sample of two different documents in the collection:
{
"_id" : "Tvq444454j",
"name" : "Jim",
"forms" : [
{
"name" : "Jorney",
"status" : "closed"
},
{
"name" : "Women",
"status" : "void"
},
{
"name" : "Child",
"status" : "closed"
},
{
"name" : "Farm",
"status" : "closed"
}
]
},
{
"_id" : "Tvq579754r",
"name" : "Tom",
"forms" : [
{
"name" : "PreOp",
"status" : "closed"
},
{
"name" : "Alert",
"status" : "closed"
},
{
"name" : "City",
"status" : "closed"
},
{
"name" : "Country",
"status" : "closed"
}
]
}
And the expected result:
{
"_id" : "Tvq579754r",
"name" : "Tom",
"forms" : [
{
"name" : "PreOp",
"status" : "closed"
},
{
"name" : "Alert",
"status" : "closed"
},
{
"name" : "City",
"status" : "closed"
},
{
"name" : "Country",
"status" : "closed"
}
]
}
As there is no standard query operator to match all of the elements of the array under this condition, the solution was found by using aggregation. This would return the _id of the documents in the collection that have all of their "forms" elements set to the status of "closed".
db.forms.aggregate([
{$unwind: "$forms" },
{$group: { _id: "$_id", status: {$addToSet: "$forms.status" }}},
{$unwind: "$status"},
{$sort: { _id: 1, status: -1 }},
{$group: {_id: "$_id", status: {$first: "$status"}}},
{$match:{ status: "closed" }}
])
So as I would be expecting to return many documents in the results, I would like to avoid issuing another find, or series of finds just to get the documents that match the returned _id's.
Considering this, is there any way that I can get the original documents back from aggregation in exactly the same form as they are in the collection, while still doing this type of filtering?