Mongoose嵌套填充

时间:2016-02-17 17:04:06

标签: node.js mongoose

我有以下两种模式:

var UserSchema = new mongoose.Schema({
  name: { type: String }
  posts: {
    owner: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }],
    contributor: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
  }
});

var PostSchema = new mongoose.Schema({
  headline: { type: String, required: true }
  authors: {
    owner: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    contributors: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
  }
});

在我的应用程序的某些时候,我需要获取有关特定用户的帖子的信息。换句话说,我需要获取用户所有者或贡献者的帖子的idheadline。但是,对于用户是其贡献者的帖子,我还需要获取其作者的信息(获取id)。

我试着开始做这样的事情:

User.findById(req.params.user_id)
    .populate({ path: 'posts.owner', select: '_id headline' })
    .populate({ path: 'posts.contributor', select: '_id headline'})
    .exec(function(err, user) {
      console.log(user);
    });

但是我不确定如何从这里继续,或者即使这是正确的做法?你能伸出援助之手吗?

2 个答案:

答案 0 :(得分:0)

如果您的帖子的标题不经常更改,您可以与用户文档一起存储,如下所示:

const UserSchema = new mongoose.Schema({
  posts: {
    owner: [{
        headline: String,
        post: { type: mongoose.Schema.Types.ObjectId, ref: 'Post' }
    }],
    contributor: [{
        headline: String,
        post: { type: mongoose.Schema.Types.ObjectId, ref: 'Post' }
    }]
  }
});

它会创建一些冗余,但是,它会让你不要只是为了获得帖子的标题而做出这么多的查询。

此外,为了保持一致性,您可以将预设中间件连接到Post模式,以便更新用户文档中的标题。你可以这样做:

PostSchema.pre('save', true, function(next, done) {
  next();

  if (!this.isModified('headline')) {
    return done();
  }

  const User = mongoose.model('User');

  return Promise.all([
    User.update({'posts.owner': this._id}, {$set: {'posts.owner.$.headline': this.headline}}, {multi: true}).exec();
    User.update({'posts.contributors': this._id}, {$set: {'posts.contributors.$.headline': this.headline}}, {multi: true}).exec();
  ])
    .then(done)
    .catch(done);
});

答案 1 :(得分:0)

我设法使用async库以稍微不同的方式获取我需要的信息。

以下是代码:

User.findById(req.params.user_id, function(err, user) {
  if(err) { throw err; }

  // if no user is found
  if(!user) {
    return res.status(404).send({ message: { user: 'There is no such user.'} });
    // something bad happened! The requested user does not exist.
  }

  async.parallel({
    owner: function(callback) {
      async.map(user.posts.owner, function(post, callback) {
        Post.findById(post, 'headline').exec(callback);
      }, callback);
    },
    contributor: function(callback) {
      async.map(user.posts.owner, function(post, callback) {
        Post.findById(post, 'headline authors.owner')
            .populate({ path: 'authors.owner', select: 'name' })
            .exec(callback);
      }, callback);
    }
  }, function(err, results) {
    if(err) { throw err; }

    return res.json(results);
  });
});