用mongodb来写blog,Nodejs中文章和comments的保存问题

用mongodb来写blog,Nodejs中文章和comments的保存问题

文章放在一个collection,comments是放在文章这个collection里面好,还是另外建立一个collection来放好?

mongodb新手。

5 回复

用mongodb来写blog,Nodejs中文章和comments的保存问题

背景

在构建博客系统时,通常会遇到如何存储文章和评论的问题。在MongoDB中,有两种主要的方式来组织这些数据:一种是将评论嵌入到文章文档中,另一种是将评论作为一个单独的集合来管理。

嵌入式 vs 引用式

  1. 嵌入式

    • 将评论直接嵌入到文章文档中。
    • 示例结构:
      {
        "title": "My First Blog Post",
        "content": "This is the content of my first blog post.",
        "comments": [
          {
            "author": "John Doe",
            "text": "Great post!",
            "createdAt": ISODate("2023-09-10T12:00:00Z")
          },
          {
            "author": "Jane Smith",
            "text": "Thanks for sharing!",
            "createdAt": ISODate("2023-09-11T14:30:00Z")
          }
        ]
      }
      
  2. 引用式

    • 将评论存储在一个单独的集合中,并通过文章的 _id 来关联。
    • 示例结构:
      • 文章集合:
        {
          "_id": ObjectId("..."),
          "title": "My First Blog Post",
          "content": "This is the content of my first blog post."
        }
        
      • 评论集合:
        {
          "postId": ObjectId("..."),
          "author": "John Doe",
          "text": "Great post!",
          "createdAt": ISODate("2023-09-10T12:00:00Z")
        }
        

选择哪种方式?

  • 嵌入式适合于评论数量较少且不经常更新的情况。这样可以减少查询次数,提高性能。
  • 引用式适合于评论数量较多且需要频繁更新的情况。这样可以更好地管理数据,避免单个文档过大。

示例代码

假设我们使用嵌入式的方式:

const mongoose = require('mongoose');

// 定义文章模型
const articleSchema = new mongoose.Schema({
  title: String,
  content: String,
  comments: [{
    author: String,
    text: String,
    createdAt: Date
  }]
});

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

// 创建一篇文章并添加评论
async function createArticleWithComments() {
  const article = new Article({
    title: 'My First Blog Post',
    content: 'This is the content of my first blog post.'
  });

  article.comments.push({
    author: 'John Doe',
    text: 'Great post!',
    createdAt: new Date()
  });

  await article.save();
}

createArticleWithComments().then(() => console.log('Article created with comments'));

总结

根据你的具体需求选择合适的方案。如果评论数量不多,嵌入式可能更简单高效;如果评论数量多且需要频繁操作,引用式可能更适合。


我补充一下:

我想到的做法是,在文章这个collection里面,加入一个array来存放所有comments,但是会不会因为comments数量比较多的时候,导致数据库性能下降。

如果下降的话,我想另外用一个comments的collection来存放,然后根据文章id来操作comments。

nodeclub的是分两个collection来设计的,comments根据文章id来操作。

如果是做博客的话,可以放到文章里面,

  1. 博客的评论一般不会太多,所以mongodb留空的空间绰绰有余
  2. 博客的文章也不会有很多,你一辈子就算每天写5篇,写20年,也才36500篇文章就算是评论很多也不太可能导致性能下降很严重

在使用 MongoDB 存储 Blog 的文章和评论时,有两种常见的设计模式:嵌入式(Embedded)和引用式(Referenced)。每种方法都有其优缺点。

嵌入式设计

将评论嵌入到文章文档中。这种方式的优点是查询方便,不需要进行多次查询。缺点是当评论数量较多时,可能会导致文档过大,影响性能。

示例代码

const mongoose = require('mongoose');

const commentSchema = new mongoose.Schema({
    author: String,
    content: String,
    createdAt: { type: Date, default: Date.now }
});

const postSchema = new mongoose.Schema({
    title: String,
    content: String,
    comments: [commentSchema],
    createdAt: { type: Date, default: Date.now }
});

const Post = mongoose.model('Post', postSchema);

// 创建一篇文章
async function createPost() {
    const post = new Post({
        title: 'My First Blog Post',
        content: 'This is my first blog post.',
        comments: [
            {
                author: 'Alice',
                content: 'Great post!',
                createdAt: new Date()
            }
        ]
    });

    await post.save();
}

createPost();

引用式设计

将评论存储在一个单独的集合中,并通过文章的 _id 来引用。这种方式的优点是评论可以独立于文章进行扩展和管理。缺点是需要进行两次查询,一次获取文章,另一次获取评论。

示例代码

const mongoose = require('mongoose');

const commentSchema = new mongoose.Schema({
    postId: { type: mongoose.Schema.Types.ObjectId, ref: 'Post' },
    author: String,
    content: String,
    createdAt: { type: Date, default: Date.now }
});

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

// 创建一篇文章
async function createPost() {
    const post = await new Post({
        title: 'My First Blog Post',
        content: 'This is my first blog post.'
    }).save();

    // 创建一条评论
    const comment = await new Comment({
        postId: post._id,
        author: 'Alice',
        content: 'Great post!',
        createdAt: new Date()
    }).save();

    return post;
}

createPost();

总结

  • 嵌入式:适用于评论数量较少且查询频率较高的场景。
  • 引用式:适用于评论数量较多且需要独立管理的情况。

选择哪种方式取决于具体的应用场景和需求。

回到顶部