我目前正在实施自己的评论系统。不幸的是,Disqus或任何其他评论平台都不符合我的要求。
我使用NodeJS和MongoDB作为后端。我需要在我的数据库上运行基本上两个查询:
可以对主题发表评论或回复评论。
嘿,很酷的帖子#top lvl comment
谢谢! #回复评论
Foo Bar! #回复回复
依旧......
所以我的数据库架构看起来像
{
id: ObjectId,
text: string,
author: { id: ObjectId, name: string },
parent: nullable ObjectId,
slug: string/number/whatever
}
如果parent
为空,则为顶级评论,否则为回复。
到目前为止相当容易,对吗?我现在遇到的问题是在帖子下面显示评论。如果只有顶级评论,那将很容易。只需获取一个特定slug的所有注释,按日期/评级/ ...对它们进行排序,然后使用我的HTML View Engine进行编译。
但实际上有回复,我只是停留在需要组织结构的地方。我想将回复嵌入我的列表中的评论
原始列表(简化)
[
{ id: 1, text: 'foo', parent: null },
{ id: 2, text: 'bar', parent: 1 },
// ...
]
预期产出
[
{ id: 1, text: 'foo', replies: [
{ id: 2, text: 'bar' },
] },
]
我尝试使用递归函数创建我的预期输出,这非常奇怪。除非它不会非常有效。所以,因为我真的感到沮丧,有点愚蠢没有解决这个问题,所以我决定请求你的帮助。
我想解决的实际问题:如何渲染我的评论,他们是否正确嵌套等。
我要问的问题是:如何以有效的方式组织我的扁平结构来解决上述问题?
答案 0 :(得分:2)
这是一种具有线性复杂性的方法:
var comments = [{
id: 3,
text: 'second',
parent: 1
}, {
id: 1,
text: 'root',
parent: null
}, {
id: 2,
text: 'first',
parent: 1
}, {
id: 5,
text: 'another first',
parent: 4
}, {
id: 4,
text: 'another root',
parent: null
}];
var nodes = {};
//insert artificial root node
nodes[-1] = {
text: 'Fake root',
replies: []
};
//index nodes by their id
comments.forEach(function(item) {
if (item.parent == null) {
item.parent = -1;
}
nodes[item.id] = item;
item.replies = [];
});
//put items into parent replies
comments.forEach(function(item) {
var parent = nodes[item.parent];
parent.replies.push(item);
});
//root node replies are top level comments
console.log(nodes[-1].replies);