【问题标题】:Mongoose 'reversed' population, i.e. populating a parent object based on the reference defined in child schemaMongoose“反向”填充,即根据子模式中定义的引用填充父对象
【发布时间】:2016-10-08 01:42:15
【问题描述】:

借用scaryguy的优秀example,修改如下:

项目组架构:

var ProjectGroupSchema = new Schema({
    projectGroupId    : String,
    title             : String
});

项目架构:

var ProjectSchema = new Schema({
    title         : {type : String, default : '', required : true},
    group         : {type: String, ref: 'ProjectGroup' },
    subscribers   : [{type: String, ref: 'User' }]
});

用户架构:

var UserSchema = new Schema({
    userId       : {type: String, require: true},
    firstName    : {type: String, required: true},
    lastName     : {type: String, required: true},
});

然后我可以做以下人口:

project.findById(req.projectId})
 .populate('subscribers')
 .populate('group')
 .exec(function(err, project){
      console.log(project);
 });

请注意,引用字段不是对象 ID。

在此示例中,项目架构具有项目组和订阅者的参考字段,这使得上述人口成为可能。

如果我想获取一个 ProjectGroup 对象,该对象包含该组下的所有项目,并且每个项目都包含其订阅者,该怎么办?

我想说我正在寻找“反向”填充,即根据子架构中定义的引用填充父对象。 目前我使用异步先查询ProjectGroup,然后根据projectGroupId查询项目。

谢谢!

【问题讨论】:

  • 什么是projectGroupIdProjectSchema 对象的 ID?
  • projectGroupId是String类型的ProjectGroup的唯一标识。
  • 也许我来晚了,但你可以看看虚拟人口

标签: node.js mongoose mongoose-populate


【解决方案1】:

如果要获取一个 ProjectGroup 对象,其中包含该组下的所有项目。您可以使用Populate Virtuals。 (猫鼬版 > 4.5.0)

在您的架构文件中创建一个虚拟架构。

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
});

并在以下查询:

ProjectGroup.find().populate('projects').exec(function(error, results) {
  /* `results.projects` is now an array of instances of `Project` */
});

如果您看不到虚拟部分,请将{ toJSON: { virtuals: true } } 设置为您的模型。

var ProjectGroupSchema = new Schema({
    projectGroupId    : String,
    title             : String
}, { toJSON: { virtuals: true } });

【讨论】:

  • 谢谢,这对我有用。我花了一段时间才发现我必须 console.log(results.toJSON({virtuals: true})); 才能看到虚拟机 :(
  • @Sam 或者,您可以在父模型中设置 { toJSON: { virtuals: true } }
【解决方案2】:

您可以通过使用聚合函数来实现这一点。首先按“projectGroup”对项目进行分组,然后填充结果。

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);
    });

});

【讨论】:

  • 感谢 vartika,解决方案很好,只是 projectGroupId 以外的 ProjectGroup 字段在结果中不可用。基本上我正在寻找一个显然还没有的“反向”人口。
猜你喜欢
  • 2020-06-18
  • 2018-06-11
  • 1970-01-01
  • 2016-08-06
  • 2017-06-02
  • 2019-01-08
  • 2016-05-27
  • 2021-07-01
  • 2022-06-14
相关资源
最近更新 更多