For any document of a specific person, you can use the populate() function, for example
var query = mongoose.model("person").find({ "name": "foo" }).populate("projects.tags");
And if you want to search for people who have any tag with "MongoDB" or "Node JS", for example, you can include the request option in the overload function of the populate() function as:
var query = mongoose.model("person").find({ "name": "foo" }).populate({ "path": "projects.tags", "match": { "en": { "$in": ["MongoDB", "Node JS"] } } });
If you want all tags existing in "project.tags" for all persons to be created for the aggregation platform. Consider starting this pipeline in the face collection and use the $lookup operator to make a left join in the tag collection
mongoose.model('person').aggregate([ { "$unwind": "$projects" }, { "$unwind": "$projects.tags" }, { "$lookup": { "from": "tags", "localField": "projects.tags", "foreignField": "_id", "as": "resultingTagsArray" } }, { "$unwind": "$resultingTagsArray" }, { "$group": { "_id": null, "allTags": { "$addToSet": "$resultingTagsArray" }, "count": { "$sum": 1 } } } ]).exec(function(err, results){ console.log(results); })
For any specific person, then apply the $match pipeline as the first step to filter documents:
mongoose.model('person').aggregate([ { "$match": { "name": "foo" } }, { "$unwind": "$projects" }, { "$unwind": "$projects.tags" }, { "$lookup": { "from": "tags", "localField": "projects.tags", "foreignField": "_id", "as": "resultingTagsArray" } }, { "$unwind": "$resultingTagsArray" }, { "$group": { "_id": null, "allTags": { "$addToSet": "$resultingTagsArray" }, "count": { "$sum": 1 } } } ]).exec(function(err, results){ console.log(results); })
Another workaround if you are using versions of MongoDB> = 2.6 or = 3.0 that do not support $lookup should populate the aggregation results as follows:
mongoose.model('person').aggregate([ { "$unwind": "$projects" }, { "$unwind": "$projects.tags" }, { "$group": { "_id": null, "allTags": { "$addToSet": "$projects.tags" } } } ], function(err, result) { mongoose.model('person') .populate(result, { "path": "allTags" }, function(err, results) { if (err) throw err; console.log(JSON.stringify(results, undefined, 4 )); }); });