我正在做一个论坛api,其中一个论坛有很多线程,线程有很多帖子,而帖子可能有很多帖子。

关系是这样完成的:

var PostSchema = new Schema({
  text: String,
  authorId: String,
  slug: Number,
  posts: [{ type: Schema.Types.ObjectId, ref: 'Post'}],
  created: { type: Date, default: Date.now }
});


父模型具有子模型的ID列表。

我将控制器设置为:

var util = require('util'),
  mongoose = require('mongoose'),
  Forum = mongoose.model('Forum'),
  Thread = mongoose.model('Thread'),
  Post = mongoose.model('Post'),
  async = require('async');

exports.show = function(req, res){
  var forums;

  var getThreads = function(forum) {
    return forum.populate('threads', function(err, _forum){
      if(err) throw new Error(err);
      forum.threads = _forum.threads;
      forum.threads.forEach(getPosts);
      return callback(err);
    });
  };

  var getPosts = function(thread) {
    return thread.populate('posts', function(err, _thread){
      if(err) throw new Error(err);
      thread.posts = _thread.posts;
      thread.posts.forEach(getComments);
      return callback(err);
    });
  };

  var getComments = function(post) {
    return post.populate('posts', function(err, _post){
      if(err) throw new Error(err);
      post.posts = _post.posts;
      post.posts.forEach(getComments);
      return callback(err);
    });
  };

  async.parallel([
    function(callback) {
      return Forum.find({ ownerId: req.params.owner_id }).exec(function(err, _forums) {
        if(err) throw new Error(err);
        forums = _forums;
        forums.forEach(getThreads);
        return callback(err);
      });
    }
  ], function(err){
      res.json(forums);
    }
  );

};


我需要制作完整的论坛对象,然后在响应中使用该对象,因为帖子有帖子,我不能只做嵌套填充。

我尝试使用异步库,但是它在promises之前执行了回调函数。

如何建立完整的论坛对象?

最佳答案

您需要以异步方式正确处理树结构。试试这种方法:

(我尚未测试,但希望它能起作用)

// ...
var Forum = mongoose.model('Forum');

exports.show = function(req, res){
  //Get the owner's forums
  Forum.find({ ownerId: req.params.owner_id }).exec(function(err, forums) {
    if(err) throw new Error(err);
    if(!forums.length) return response.json(forums); //Send an empty array if no forums where found

    //Build forums one by one
    var forum = forums.shift();
    buildForum(forum, function () {
      forum = forums.shift();
      if (forum) {
        buildForum(forum, this);
      } else {
        //All forums were built.
        res.json(forums);
      };
    });
  });

  var buildForum = function (forum, onSuccess) {
    forum.populate('threads', function(err, forum){
      if(err) throw new Error(err);
      if(!forum.threads.length) return onSuccess();

      //Build threads one by one
      var threads = forum.threads;
      var thread = threads.shift();
      buildThread(thread, function () {
        thread = threads.shift();
        if (thread) {
          buildThread(thread, this);
        } else {
          //All threads were built.
          onSuccess();
        };
      });
    });
  };

  var buildThread = function (thread, onSuccess) {
    thread.populate('posts', function(err, thread){
      if(err) throw new Error(err);
      if(!thread.posts.length) return onSuccess();

      //Build posts one by one
      var posts = thread.posts;
      var post = posts.shift();
      buildPost(post, function () {
        post = posts.shift();
        if (post) {
          buildPost(post, this);
        } else {
          //All posts were built.
          onSuccess();
        };
      });
    });
  };

  var buildPost = function (post, onSuccess) {
    post.populate('posts', function(err, post){
      if(err) throw new Error(err);
      if(!post.posts.length) return onSuccess();

      //Build comments one by one
      var posts = post.posts;
      var _post = posts.shift();
      buildPost(_post, function () {
        _post = posts.shift();
        if (_post) {
          buildPost(_post, this);
        } else {
          //All comments were built.
          onSuccess();
        };
      });
    });
  };
};

10-07 14:30