Mongoose 'reversed' population, i.e. populating a parent object based on the reference defined in child schema

柔情痞子 提交于 2019-12-19 07:22:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!