Reputation: 70406
Collection:
[{
_id: 'Foo',
plugs: [
{ type: 'CE', code: 12 },
{ type: 'SH': code: 34 }
]
},{
_id: 'Bar',
plugs: [
{ type: 'T2', code: 23 },
{ type: 'T2': code: 43 }
]
}]
In the plug array may be entries with the same type. When I make an aggregation I want to filter the documents by type of plugs. E.g. return only documents that contains a plug of type T2. How can I do that in mongodb? I am aware of the $in query but this only works for a simple array of values.
Upvotes: 3
Views: 5401
Reputation: 151102
Normal .find()
based projection works well when there is only a single match expected, but the aggregation framework is presently the only thing that will return "multiple" results from an array:
db.collection.aggregate([
// Still makes sense to "filter" the documents
{ "$match": { "plugs.type": "T2" } },
{ "$unwind": "$plugs" },
// This actually "filters" the array content
{ "$match": { "plugs.type": "T2" } },
{ "$group": {
"_id": "$_id",
"plugs": { "$push": "$plugs" }
}}
])
Or even with MongoDB 2.6 or greater you can do this with "unique" entries under a "set" constraint:
db.collection.aggregate([
{ "$match": { "plugs.type": "T2" } },
{ "$project": {
"plugs": {
"$setDiffernce": [
{ "$map": {
"input": "$plugs",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.type", "T2" ] },
"$$el",
false
]
}
}},
[false]
]
}
}}
])
But really you are only talking about "document matching" and not "element filtering", so here the aggregation framework is overkill. Just match the documents:
db.collection.find({ "plugs.type": "T2" })
That will only return the "documents" where at least one of the elements matches the condition. This is part of the basic understanding of how query patterns actually work in MongoDB.
The base type here uses "dot notation" for specifying "part" of a document identity. It's a basic part again of how MongoDB queries work.
Upvotes: 5