Mongodb aggregated request with $ lookup

Received two sets, tags and faces.

Tag model

:

{ en: String, sv: String } 

personal model:

 { name: String, projects: [ title: String, tags: [ { type: Schema.ObjectId, ref: 'tag' } ] ] } 

I want the query to return all tags that are used in the user model. All documents.

Someh how

 var query = mongoose.model('tag').find({...}); 

Or should I somehow use a common approach to this?

+7
mongodb mongoose mongodb-query aggregation-framework
source share
2 answers

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 )); }); }); 
+19
source share

If you are using MongoDb version 3.2, you can use $ lookup , which performs a left outer join.

+1
source share

All Articles