我正在做论坛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);
}
);
};
我需要制作完整的论坛对象,然后在回复中使用它,因为帖子有帖子我不能只做一个嵌套的填充。
我尝试使用异步lib,但它在promises之前执行回调函数。
如何构建完整的论坛对象?
答案 0 :(得分:1)
您需要以异步方式正确处理树结构。试试这种方法:
(我没有测试,但希望它有效)
// ...
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();
};
});
});
};
};
答案 1 :(得分:1)
这是我的解决方案,只是@Danypype解决方案中的一个小修复。
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();
var responseForums = [forum];
buildForum(forum, function () {
forum = forums.shift();
if (forum) {
responseForums.push(forum);
buildForum(forum, arguments.callee);
} else {
//All forums were built.
res.json(responseForums);
};
});
});
var buildForum = function (forum, onSuccess) {
forum.populate('threads', function(err, forum){
if(err) throw new Error(err);
if(!forum.threads.length) return onSuccess();
if(forum.length == 1) return onSuccess();
var thread = forum.threads.shift();
var responseThreads = [thread];
buildThread(thread, function () {
thread = forum.threads.shift();
if (thread) {
responseThreads.push(thread)
buildThread(thread, arguments.callee);
} else {
//All threads were built.
forum.threads = responseThreads;
onSuccess();
};
});
});
};
var buildThread = function (thread, onSuccess) {
thread.populate('posts', function(err, thread){
if(err) throw new Error(err);
if(!thread.posts.length) return onSuccess();
var post = thread.posts.shift();
var responsePosts = [post]
buildPost(post, function () {
post = thread.posts.shift();
if (post) {
responsePosts.push(post);
buildPost(post, arguments.callee);
} else {
//All posts were built.
thread.posts = responsePosts;
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 _post = post.posts.shift();
var response_posts = [_post];
buildPost(_post, function () {
_post = post.posts.shift();
if (_post) {
response_posts.push(_post);
buildPost(_post, arguments.callee);
} else {
//All comments were built.
post.posts = response_posts;
onSuccess();
};
});
});
};
};