我正在做一个论坛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();
};
});
});
};
};