关于mongodb评论功能数据库设计在Nodejs中的疑惑

关于mongodb评论功能数据库设计在Nodejs中的疑惑

1.嵌入 直接将评论文档嵌入到文章文档里面,这样以1K一条评论,那16M可以存1.6W条,这样有个评论数的上限,但是存取速度会比2中优化?

2.搞SQL的那套,建个集合,专门装入评论,所有用户,所有文章的评论走在这个集合中,那查询的岂不是~~~~,不说了?

3.鉴于1和2,大型网站的评论在存储设计上是如何做的,如果仅用Mongodb,怎么设计好一些?

8 回复

关于MongoDB评论功能数据库设计在Node.js中的疑惑

在设计一个评论功能时,通常需要考虑数据模型的选择、性能优化以及扩展性。以下是针对你的问题的一些分析和建议:

1. 嵌入式文档

将评论直接嵌入到文章文档中是一个常见的做法,尤其是在评论数量较少的情况下。例如:

const articleSchema = new mongoose.Schema({
    title: String,
    content: String,
    comments: [
        {
            user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
            text: String,
            createdAt: { type: Date, default: Date.now }
        }
    ]
});

这种方式的优点是读取速度快,因为所有评论都与文章一起加载。缺点是当评论数量较多时,文章文档会变得非常大,影响性能和可维护性。

2. 分离式文档

另一种方法是将评论存储在一个单独的集合中。这样可以避免单个文档过大,并且可以更好地利用索引和查询优化。

const commentSchema = new mongoose.Schema({
    articleId: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
    user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    text: String,
    createdAt: { type: Date, default: Date.now }
});

const Comment = mongoose.model('Comment', commentSchema);

这种方式的优点是可以轻松地处理大量的评论,并且可以通过索引提高查询效率。缺点是需要进行额外的查询来获取评论列表。

3. 大型网站的设计实践

对于大型网站,通常会结合使用上述两种方法。例如:

  • 使用嵌入式文档存储少量评论(如最近的10条评论)。
  • 将所有评论存储在一个独立的集合中,以便于查询和分页。

这种混合模式可以提供较好的性能和扩展性。例如:

// 文章模型
const articleSchema = new mongoose.Schema({
    title: String,
    content: String,
    recentComments: [
        {
            user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
            text: String,
            createdAt: { type: Date, default: Date.now }
        }
    ],
    commentCount: Number
});

// 评论模型
const commentSchema = new mongoose.Schema({
    articleId: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
    user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    text: String,
    createdAt: { type: Date, default: Date.now }
});

const Article = mongoose.model('Article', articleSchema);
const Comment = mongoose.model('Comment', commentSchema);

通过这种方式,你可以在文章页面显示最近的评论,同时也可以查询所有评论。

希望这些示例代码和解释能帮助你更好地理解MongoDB在Node.js中的评论功能数据库设计。


这帖子好不吸引人

同疑惑,如果单独的建立一个评论表,感觉就sql了,嵌入到文章里,又比较乱,复杂一点的就不好进行查询

文章结尾还说说了看情况在1和2间选择,现实中的海量消息的引用页是类似这种设计?

评论少的用嵌入,一般用单独的集合

同意楼上的看法。嵌入式的应用一般用于子记录和主纪录有密切关系,而且子记录数量不大。

针对你的问题,我们可以通过分析几种不同的数据库设计方案来解决评论功能的实现。以下是一些具体的建议:

方案一:嵌入式(Embedded)

你可以直接将评论数据嵌入到文章文档中,这种方法适用于评论数量较少的情况。

优点:

  • 查询速度快。
  • 数据一致性好。

缺点:

  • 当评论数量较大时,可能会导致单个文档过大(MongoDB单个文档大小限制为16MB)。
  • 更新或删除评论操作可能比较复杂。

示例代码:

const mongoose = require('mongoose');

const articleSchema = new mongoose.Schema({
    title: String,
    content: String,
    comments: [
        {
            user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
            text: String,
            createdAt: { type: Date, default: Date.now }
        }
    ]
});

const Article = mongoose.model('Article', articleSchema);

// 添加评论
async function addComment(articleId, userId, text) {
    const article = await Article.findById(articleId);
    article.comments.push({ user: userId, text });
    await article.save();
}

module.exports = Article;

方案二:引用式(Referenced)

创建一个单独的集合用于存储所有评论,通过引用的方式将评论与文章关联起来。这种方法适用于评论数量较多的情况。

优点:

  • 单个文档大小不受限制。
  • 查询和更新操作更加灵活。

缺点:

  • 查询速度可能会受到一定影响。
  • 需要处理更多的关系管理逻辑。

示例代码:

const mongoose = require('mongoose');

const commentSchema = new mongoose.Schema({
    user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
    article: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
    text: String,
    createdAt: { type: Date, default: Date.now }
});

const Comment = mongoose.model('Comment', commentSchema);

// 添加评论
async function addComment(articleId, userId, text) {
    const comment = new Comment({ user: userId, article: articleId, text });
    await comment.save();
}

module.exports = Comment;

大型网站的实践

对于大型网站,通常会采用分片(Sharding)等技术来提高性能和扩展性。在MongoDB中,你可以使用分片来分散大量数据,从而避免单个节点成为瓶颈。

总结

选择哪种方案取决于具体的应用场景。如果你的应用对评论数量有严格的限制,并且希望简化查询逻辑,可以选择嵌入式方法;如果你的应用需要处理大量的评论数据,并且希望保持较高的灵活性和可扩展性,则应该选择引用式方法。

回到顶部