映射模式关系
在设计模式时,请考虑应用程序需要如何查询和返回相关数据。如何映射数据实体之间的关系会影响应用程序的性能和可扩展性。
处理相关数据的推荐方法是将其嵌入子文档中。 通过嵌入相关数据,应用程序可以通过单次读取操作查询所需的数据,避免缓慢的 $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" } )
后续步骤
在映射应用程序数据的关系后,架构设计过程的下一步是应用设计模式来优化架构。请参阅应用设计模式。