MongoDB - 数据建模
MongoDB - 数据建模
Section titled “MongoDB - 数据建模”MongoDB 中的数据具有灵活的模式(schema)。与传统 SQL 数据库不同,同一个集合中的文档不必具有相同的字段集或结构。这种灵活性是一个强大的特性,但精心设计的数据模型对于应用程序的性能、可扩展性和可维护性至关重要。MongoDB 数据建模的关键在于根据应用程序的查询和更新需求来构建数据。
核心数据建模模式
Section titled “核心数据建模模式”MongoDB 的文档模型允许您以两种主要方式构建数据:将相关数据嵌入到单个文档中,或在不同集合之间引用数据。
1. 嵌入式(非范式化)模型
Section titled “1. 嵌入式(非范式化)模型”在此模型中,相关数据嵌套在单个文档内。这也被称为非范式化(denormalization)。这种方法允许您在单个数据库查询中检索所有相关信息,效率非常高。
用例: 一个包含用户地址信息的 user 文档。由于地址本质上是用户个人资料的一部分,并且几乎总是与用户一起查询,因此嵌入是一个很好的选择。
{ "_id": ObjectId("64f7c7f8b3e9a1e8a8b1a8d9"), "username": "jane.doe", "email": "jane.doe@example.com", "address": { "street": "123 Main St", "city": "Anytown", "state": "CA", "zip": "12345" }}优点: 所有数据都在一个操作中检索,读取速度更快。在单个文档上的操作是原子性的。
缺点: 如果嵌入的信息也需要单独使用,可能导致大型文档和数据重复。
2. 引用式(范式化)模型
Section titled “2. 引用式(范式化)模型”在此模型中,您通过在单独的集合中存储引用(通常是相关文档的 _id 字段)来维护文档之间的关系。这类似于传统的_关系型数据库_模型,当相关数据量大、频繁更新或独立使用时,这种方法很有用。
用例: 一个包含 products(产品)和 orders(订单)的电子商务应用程序。每个 order 文档都引用其包含的 products。这避免了在每个订单中重复产品信息。
产品集合 (Products Collection):
{ "_id": ObjectId("A123"), "name": "Wireless Mouse", "price": 29.99, "stock": 150}{ "_id": ObjectId("B456"), "name": "Mechanical Keyboard", "price": 89.99, "stock": 75}订单集合 (Orders Collection):
{ "_id": ObjectId("ORDER_001"), "userId": ObjectId("USER_XYZ"), "orderDate": ISODate("2023-09-06T10:00:00Z"), "items": [ { "productId": ObjectId("A123"), "quantity": 2 }, { "productId": ObjectId("B456"), "quantity": 1 } ]}优点: 减少数据重复,更容易管理频繁更改的相关数据。
缺点: 需要单独的查询($lookup 聚合阶段)来检索相关数据,这可能比读取嵌入式文档慢。
Schema 设计的关键考虑因素
Section titled “Schema 设计的关键考虑因素”- 关系类型: 对于“一对少量”(one-to-few)关系(例如,用户及其地址),使用嵌入。对于“一对多”(one-to-many)(例如,产品及其部件)或“多对多”(many-to-many)关系(例如,学生和课程),使用引用。
- 数据访问模式: 设计您的模式以支持您最频繁的查询。如果您总是需要将数据一起使用,请将其嵌入。如果您单独访问它,请引用它。
- 原子性: 单个文档上的操作是原子性的。如果您需要对相关数据进行原子读/写操作,嵌入是首选模型。
- 数据重复: 如果能显著提高读取性能,一些重复是可以接受的。磁盘空间通常比计算时间便宜。
- 聚合的模式: 对于复杂的报告,您可能需要以最适合_聚合框架_的方式构建数据。
- 索引: 您的数据模型将影响您的索引策略。确保您的模式允许在频繁查询的字段上建立高效索引。
示例:建模博客文章
Section titled “示例:建模博客文章”让我们为一篇博客文章建模,它包含标题、内容、作者、标签和评论。评论是特定于文章的,并且通常与文章一起显示。这使其成为嵌入式模型的首选。
在关系型(SQL)数据库中,这通常需要至少三张表(posts、comments、tags)在查询时进行连接。在 MongoDB 中,我们可以用一个直观的文档来建模。
{ "_id": ObjectId("POST_ID_123"), "title": "我的第一篇 MongoDB 文章", "content": "这是博客文章的正文...", "author_id": ObjectId("AUTHOR_ID_456"), // 作者ID "author_name": "John Smith", // 为了性能而重复 "url_slug": "my-first-mongodb-post", // URL别名 "tags": ["mongodb", "database", "nosql"], "likes": 150, "published_at": ISODate("2023-09-01T14:30:00Z"), // 发布时间 "comments": [ // 评论列表 { "user_id": ObjectId("USER_ID_789"), // 用户ID "username": "评论者一号", "message": "好文章!非常有帮助。", // 消息内容 "createdAt": ISODate("2023-09-02T11:00:00Z"), // 创建时间 "likes": 12 // 点赞数 }, { "user_id": ObjectId("USER_ID_101"), "username": "另一个读者", "message": "谢谢分享。", "createdAt": ISODate("2023-09-03T16:45:00Z"), "likes": 5 } ]}这种单文档模型意味着当用户查看博客文章时,所有必要的信息(包括其所有评论)都可以通过一次快速的读取操作来检索,从而提供卓越的用户体验。