问题
I am trying to get subdocuments which are matched my conditions.
My MongoDB query like that:
db.SCSIssue.find(
{ _id: ObjectId("5439a2992ea8cc0f70feef2d") },
{ Statuses: { $elemMatch: { StatusID: { $gte : NumberLong(521055087020736513) } } } }
)
My schema like that:
{
....
"_id": ObjectId("5439a2992ea8cc0f70feef2d"),
....
"Statuses": [{
....
"StatusID": NumberLong(525623822633172993),
},{
....
"StatusID": NumberLong(521055087020736513),
},{
....
"StatusID": NumberLong(521060802959532033),
}]
....
},
{
....
"_id": ObjectId("543c04662ea8cd11ec4dda5f"),
....
"Statuses": [{
....
"StatusID": NumberLong(535623822633172993),
},{
....
"StatusID": NumberLong(541055087020736513),
},{
....
"StatusID": NumberLong(551060802959532033),
}]
....
},
....
Query result:
{
"_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
"Statuses" : [{
....
"StatusID": NumberLong(525623822633172993),
....
}]
}
Expected result:
{
"_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
"Statuses" : [{
....
"StatusID": NumberLong(521055087020736513),
},{
....
"StatusID": NumberLong(521060802959532033),
}]
}
Briefly, I would like to get subdocuments in array (Statuses) which are greater than or equal my condition and same time which are _id's equal to my condition. I have read lots of answer about that. All of them like my question but in my situation its not work expected.
What am I missing? Thank you.
回答1:
There is nothing wrong with the behavior of $elemMatch
. It works as expected. The doc also says:
However, the $elemMatch projection returns only the first matching element from the array.
As a rule of thumb whenever you project an array
using $elemMatch
, only one of the elements will be projected at most. If none of the elements in the array match, the field won't be projected at all.
So the result you get is correct, only the first item in the array that has matched the condition in $elemMatch
will be projected
.
{
"_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
"Statuses" : [{
....
"StatusID": NumberLong(525623822633172993),
....
}]
}
You may try changing the order of documents in the statuses array, and may get a different matching document if that document appears ahead of the other matching documents in the array.
Refer: $elemMatch
Coming to your requirement, if you want all the matching array elements in your result, you need to perform an aggregation operation.
Match
those documents having the required _id and those documents which contain the status sub document that we are searching for.unwind
the statuses array.- Again
match
the individual unwinded documents. - Finally
group
the matched documents by_id
.
The Code:
db.collection.aggregate([
{$match:{ "_id": ObjectId("5439a2992ea8cc0f70feef2d"),
"Statuses.StatusID":{$gte : NumberLong(525623822633172993)}}},
{$unwind:"$Statuses"},
{$match:{"Statuses.StatusID":{$gte : NumberLong(525623822633172993)}}},
{$group:{"_id":"$_id",statuses:{$push:"$Statuses"}}}
])
which will give you all the matching sub documents in the array.
来源:https://stackoverflow.com/questions/27093562/mongodb-elemmatch-does-not-work-expected