如何映射数据实体之间的关系会影响应用程序的性能和可扩展性。
处理相关数据的推荐方法是将其嵌入子文档中。 通过嵌入相关数据,应用程序可以通过单次读取操作查询所需的数据,避免缓慢的 $lookup操作。
对于某些用例,您可以使用引用来指向单独集合中的相关数据。
关于此任务
如要确定是否应嵌入相关数据或使用引用,请考虑以下目标对应用程序的相对重要性:
- 改进相关数据的查询
- 如果应用程序经常查询一个实体以获取有关另一个实体的数据,请嵌入该数据,避免频繁执行
$lookup操作。 - 改进从不同实体返回的数据
- 如果您的应用程序从相关实体一起返回数据,请将数据嵌入到单个集合中。
- 改进更新性能
- 如果您的应用程序经常更新相关数据,请考虑将数据存储在自己的集合中,并通过引用来访问这些数据。当使用引用时,只需在一个地方更新数据,这将减少应用程序的写入工作负载。
要详细学习;了解嵌入式数据和引用的优点,请参阅链接相关数据。
步骤
识别模式中的相关数据
确定应用程序查询的数据以及实体之间的关系。
考虑您在识别应用程序工作负载步骤中识别的操作。请注意这些操作写入和返回的信息,以及哪些信息在多个操作之间重叠。
为相关数据创建模式映射
您的架构映射应显示相关的数据字段以及这些字段之间的关系类型(一对一、一对多、多对多)。
模式映射可以类似于 实体关系模型。
示例
以下示例介绍了如何根据应用程序的需求优化不同查询的模式。
本页上的示例使用sample_mflix示例数据集中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载示例数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。
优化电影查询
如果您的应用程序查询电影中的 title 等字段,请将相关信息嵌入 movies集合中。嵌入数据可在单个操作中返回应用程序所需的所有内容。
以下文档优化了对电影的查询:
db.movies.insertOne( { title: "The Brutalist", year: 2024, runtime: 215, genres: [ "Drama", "History" ], comments: [ { name: "joel_m", email: "joel_m@gameofthron.es", text: "Visually stunning!" } ], user: { name: "Joel M", email: "joel_m@gameofthron.es" } } )
优化电影和用户的查询
如果您的应用程序分别返回电影信息和用户信息,请考虑将电影和用户存储在单独的集合中。这种模式设计减少了返回用户信息所需的工作,并允许您仅返回用户信息,而不包含不需要的字段。
在以下模式中,movies集合包含 userId字段,它是对 users集合的引用。
电影集合
db.movies.insertOne( { title: "A Complete Unknown", year: 2024, runtime: 141, genres: [ "Biography", "Drama", "Music" ], userId: 987 } )
用户集合
db.users.insertOne( { _id: 987, name: "Joel M", email: "joel_m@gameofthron.es" } )
后续步骤
在映射应用程序数据的关系后,架构设计过程的下一步是应用设计模式来优化架构。请参阅应用设计模式。