文档结构设计

MongoDB 不需要提前创建表结构,但不代表不用设计结构。

真实项目里,文档结构设计非常重要。

一、先从接口返回的数据思考

假设文章详情接口要返回:

{
  "title": "MongoDB 入门",
  "content": "正文内容",
  "author": {
    "id": "665f0e0b6f8c2b5f8e123456",
    "username": "zhangsan"
  },
  "tags": ["mongodb", "database"],
  "createdAt": "2026-06-07T10:00:00Z"
}

MongoDB 文档可以接近这个结构:

db.posts.insertOne({
  title: "MongoDB 入门",
  content: "正文内容",
  author: {
    id: ObjectId("665f0e0b6f8c2b5f8e123456"),
    username: "zhangsan"
  },
  tags: ["mongodb", "database"],
  createdAt: new Date()
})

这种文档很适合直接给接口读取。

二、字段命名建议

建议使用一种风格并保持统一。

常见做法:

{
  username: "zhangsan",
  createdAt: new Date(),
  updatedAt: new Date()
}

也就是小驼峰。

不要在同一个项目里混用:

createdAt
created_at
CreatedAt

混用会让后端代码、接口文档和查询条件都变乱。

三、常见公共字段

很多集合都会有这些字段:

{
  createdAt: new Date(),
  updatedAt: new Date(),
  deletedAt: null
}

含义:

字段说明
createdAt创建时间
updatedAt更新时间
deletedAt软删除时间,null 表示未删除

如果使用软删除,查询时记得过滤:

db.posts.find({
  deletedAt: null
})

四、不要让文档无限变大

错误示例:

{
  title: "热门文章",
  comments: [
    { content: "评论 1" },
    { content: "评论 2" }
  ]
}

如果评论可能有几十万条,就不要全部内嵌到文章文档里。

更适合拆成 comments 集合:

db.comments.insertOne({
  postId: ObjectId("665f0e0b6f8c2b5f8e123456"),
  content: "评论内容",
  createdAt: new Date()
})

文档设计要考虑数据增长。

五、读多还是写多

设计文档结构时,先问:

  1. 这个数据经常一起读取吗?
  2. 这个嵌套字段会不会频繁单独更新?
  3. 数组会不会持续增长?
  4. 是否需要按某个字段查询和排序?

如果经常一起读取,而且数量有限,可以考虑内嵌。

如果会无限增长,或者需要单独查询,通常拆成单独集合。

六、示例:用户资料

用户资料通常适合放在用户文档里:

db.users.insertOne({
  username: "zhangsan",
  email: "zhangsan@example.com",
  profile: {
    nickname: "小张",
    city: "杭州",
    bio: "后端开发"
  },
  createdAt: new Date()
})

因为资料和用户通常一起读取,体积也不会无限增长。