问题
Let's borrow the excellent example from scaryguy with modification as below:
Project Group Schema:
var ProjectGroupSchema = new Schema({
projectGroupId : String,
title : String
});
Project Schema:
var ProjectSchema = new Schema({
title : {type : String, default : '', required : true},
group : {type: String, ref: 'ProjectGroup' },
subscribers : [{type: String, ref: 'User' }]
});
User Schema:
var UserSchema = new Schema({
userId : {type: String, require: true},
firstName : {type: String, required: true},
lastName : {type: String, required: true},
});
Then I can do following population:
project.findById(req.projectId})
.populate('subscribers')
.populate('group')
.exec(function(err, project){
console.log(project);
});
Note that the reference fields are not Object IDs.
In this example the project schema has the reference fields to both the project group and subscribers which makes the above population possible.
What if I want to get a ProjectGroup object, which contains all the projects under that group, and each project contains its subscribers?
I'd say I'm looking for a 'reversed' population, i.e. populating a parent object based on the reference defined in child schema. At the moment I use async to query the ProjectGroup first, then query the projects based on the projectGroupId.
Thanks!
回答1:
You can achieve this by using aggregate function. First group projects by "projectGroup" and then populate result.
project.aggregate([
{$group: {_id: "$group", projects: {$push: "$$ROOT"}}}
],
function(err,results) {
user.populate( results, { "path": "projects.subscribers" }, function(err,results) {
if (err)
console.log(err);
res.send(results);
});
});
回答2:
If you want to get a ProjectGroup object, which contains all the projects under that group. You can use Populate Virtuals. (Mongoose version > 4.5.0)
create a virtual schema in your schema file.
ProjectGroupSchema.virtual('projects', {
ref: 'Project', // The model to use
localField: 'projectGroupId', // Your local field, like a `FOREIGN KEY` in RDS
foreignField: 'group', // Your foreign field which `localField` linked to. Like `REFERENCES` in RDS
// If `justOne` is true, 'members' will be a single doc as opposed to
// an array. `justOne` is false by default.
justOne: false
});
and query in following:
ProjectGroup.find().populate('projects').exec(function(error, results) {
/* `results.projects` is now an array of instances of `Project` */
});
If you cannot see virtuals part, plese set { toJSON: { virtuals: true } }
to your model.
var ProjectGroupSchema = new Schema({
projectGroupId : String,
title : String
}, { toJSON: { virtuals: true } });
来源:https://stackoverflow.com/questions/37691476/mongoose-reversed-population-i-e-populating-a-parent-object-based-on-the-ref