MongoDB架构:如何以可扩展的方式存储大量数组或子文档

MongoDB architecture: how to store a large amount of arrays or sub documents in a scalable way

我目前正在开发一个博客应用程序,用户可以在其中创建自己的博客,每个博客中都有博文。当每个博客都有很多博文时,我正在考虑构建一个可扩展的数据库。

那么我的数据库结构是否更好:

blog1 : {
 blogname : 'blog1',
 blogposts: [array of blogposts] 
},

blog2 : {
 blogname : 'blog2',
 blogposts: [array of blogposts] 
}

或者我应该创建一个包含所有博文的单独集合,如下所示:

blogpost1: {
 id: 'blogpost1',
 content: {blogpost content in json format}
},
blogpost2: {
 id: 'blogpost2',
 content: {blogpost content in json format}
}

并在博客集中引用它们。

我想知道当有很多博文时,选择哪个更好。因为我记得在 MongoDB 文档的某个地方读过,不建议在文档中使用可以超出范围的数组,所以方法 #1 并不理想,对吗?

为什么必须是其中之一?

将博客 post 存储在与博客相同的文档中非常好,只要单个 post 不是很大,而且数量不是很多。

将 post 存储在单独的集合中适用于更大的 post 和繁忙的博客,但会添加额外的查询或查找以进行检索。

我认为您的用户的输出预计 运行 范围从稀疏到多,个人 post 的范围从几十字节到几兆字节不等。

对于不太活跃的博客上的小 post,将 post 存储在博客文档中以便高效检索。

对于繁忙的博客,将它们存储在存档集合中。也许将最近的 post 或最流行的 post 存储在博客文档中,这样您就不必每次都引用其他集合。

您还需要弄清楚如何在文档之间拆分 post。 MongoDB 对单个文档有 16MB 的限制,因此如果您的任何用户制作了巨大的 posts,您需要能够将它们存储在某个地方。

你写的问题似乎是在问遵循关系模型还是严格的文档模型更好。我认为实际上两者都不是完美的选择,混合和灵活的方法会更好。

创建数据库时,我发现考虑我将提出的请求很有用。

博客应用程序用户可能希望搜索所有博客或按某些条件查找博主。

在这种情况下,将博主和博客分开 collections 效果最好。然后构建您的文档,以便博主 link 访问他们的博客,反之亦然。

这可以通过 Mongoose Schemas 来完成 (https://mongoosejs.com/docs/index.html)。

// models/blogger.js
const mongoose = require('mongoose')

const bloggerSchema = mongoose.Schema({
  blogs: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Blog'
    }
  ],
  name: String
})

bloggerSchema.set('toJSON', {
  transform: (document, returnedObject) => {
    const blogger = returnedObject

    blogger.id = blogger._id.toString()
    delete blogger._id
    delete blogger.__v
  }
})

module.exports = mongoose.model('Blogger', bloggerSchema)

然后使用填充您的请求:

// controllers/bloggers.js
const bloggersRouter = require('express').Router()
const Blogger = require('../models/blogger')

bloggersRouter.get('/', async (request, response) => {
  const bloggers = await Blogger.find({}).populate(
    'blogs', {
      title: 1
    }
  )
  response.json(bloggers.map(blogger => blogger.toJSON()))
})

module.exports = bloggersRouter

这样您就不必将博客全部添加到博主文档中,只需在博主初始视图中包含标题或您需要的任何其他内容。

您也可以考虑限制博客的长度,以便更好地控制数据,然后考虑 Joe 建议的选项。