映射模式关系
在设计您的模式时,请考虑您的应用程序如何查询和返回相关数据。您如何映射数据实体之间的关系会影响应用程序的性能和可扩展性。
处理相关数据的首选方法是将其嵌入子文档中。嵌入相关数据可以让您的应用程序通过单个读取操作查询所需数据,并避免缓慢的$lookup
操作。
对于某些用例,您可以使用引用指向另一个集合中的相关数据。
关于此任务
为了确定是否应嵌入相关数据或使用引用,请考虑以下目标对您应用程序相对的重要性
- 提高相关数据的查询
- 如果您的应用程序经常查询一个实体以返回另一个实体的数据,则嵌入数据以避免频繁的
$lookup
操作。 - 提高不同实体返回的数据
- 如果您的应用程序从相关实体中返回数据,请将这些数据嵌入到单个集合中。
- 提高更新性能
- 如果您的应用程序经常更新相关数据,考虑将数据存储在其自己的集合中,并使用引用来访问它。当您使用引用时,通过仅在单个位置更新数据,可以减少应用程序的写工作负载。
要了解嵌入数据和引用的优势,请参阅嵌入数据与引用。
开始之前
映射关系是架构设计过程的第二步。在映射关系之前,确定应用程序的工作负载以确定所需的数据。
步骤
2
为您相关的数据创建一个模式图
您的模式图应显示相关数据字段及其之间的关系类型(一对一、一对多、多对多)。
您的模式图可以类似于实体关系模型.
3
选择是嵌入相关数据还是使用引用
嵌入数据或使用引用的决定取决于您的应用程序的常见查询。回顾您在识别应用程序工作负载步骤中确定的查询,并使用本页前面提到的指南来设计您的模式以支持频繁和关键查询。
配置您的数据库、集合和应用逻辑以匹配您选择的方法。
示例
以下是一个博客应用程序的模式图的示例

以下示例展示了如何根据应用程序的需求优化不同的查询。
优化文章查询
如果您的应用程序主要查询文章以获取标题等信息,请在articles
集合中嵌入相关信息,以便在单个操作中返回应用程序所需的所有数据。
以下文档针对文章查询进行了优化
db.articles.insertOne( { title: "My Favorite Vacation", date: ISODate("2023-06-02"), text: "We spent seven days in Italy...", tags: [ { name: "travel", url: "<blog-site>/tags/travel" }, { name: "adventure", url: "<blog-site>/tags/adventure" } ], comments: [ { name: "pedro123", text: "Great article!" } ], author: { name: "alice123", email: "alice@mycompany.com", avatar: "photo1.jpg" } } )
优化文章和作者查询
如果您的应用程序分别返回文章信息和作者信息,考虑将文章和作者存储在单独的集合中。这种模式设计可以减少返回作者信息所需的工作量,并允许您仅返回作者信息,而不包括不需要的字段。
在以下模式中,articles
集合包含一个authorId
字段,该字段是对authors
集合的引用。
文章集合
db.articles.insertOne( { title: "My Favorite Vacation", date: ISODate("2023-06-02"), text: "We spent seven days in Italy...", authorId: 987, tags: [ { name: "travel", url: "<blog-site>/tags/travel" }, { name: "adventure", url: "<blog-site>/tags/adventure" } ], comments: [ { name: "pedro345", text: "Great article!" } ] } )
作者集合
db.authors.insertOne( { _id: 987, name: "alice123", email: "alice@mycompany.com", avatar: "photo1.jpg" } )
下一步
在为您的应用程序数据映射关系后,模式设计过程的下一步是应用设计模式以优化您的模式。请参阅应用设计模式。