文档菜单
文档首页
/
MongoDB 手册
/

处理重复数据

本页内容

  • 关于此任务
  • 示例:电子商务模式中的重复数据
  • 步骤
  • 复制数据的优势
  • 示例:产品评论的重复数据
  • 步骤
  • 复制数据的优势
  • 了解更多

当你将相关数据嵌入到单个文档中时,你可能会在两个集合之间重复数据。复制数据允许你的应用程序在单个查询中查询多个实体的相关信息,同时在模型中逻辑上分离实体。

关于数据复制的担忧之一是增加了存储成本。然而,优化访问模式的好处通常超过存储成本增加的潜在成本。

在复制数据之前,请考虑以下因素:

  • 需要更新复制的数据的频率。频繁更新复制的数据可能会导致沉重的负载和性能问题。然而,处理不频繁更新的额外逻辑比在读取操作中执行连接(查找)的成本要低。

  • 当数据被复制时,读取性能的提升。复制数据可以消除在多个集合之间执行连接的需求,这可以提高应用程序性能。

以下示例展示了如何在电子商务应用模式中复制数据以改进数据访问和性能。

1
use eCommerce
2

电子商务数据库中创建以下集合

集合名称
描述
示例文档
customers
存储客户信息,如姓名、电子邮件和电话号码。
db.customers.insertOne( {
customerId: 123,
name: "Alexa Edwards",
email: "a.edwards@randomEmail.com",
phone: "202-555-0183"
} )
products
存储产品信息,如价格、尺寸和材料。
db.products.insertOne( {
productId: 456,
product: "sweater",
price: 30,
size: "L",
material: "silk",
manufacturer: "Cool Clothes Co"
} )
orders
存储订单信息,如日期和总价。在orders集合的文档中,lineItems字段包含该订单对应的产品。
db.orders.insertOne( {
orderId: 789,
customerId: 123,
totalPrice: 45,
date: ISODate("2023-05-22"),
lineItems: [
{
productId: 456,
product: "sweater",
price: 30,
size: "L"
},
{
productId: 809,
product: "t-shirt",
price: 10,
size: "M"
},
{
productId: 910,
product: "socks",
price: 5,
size: "S"
}
]
} )

以下从products集合的属性在orders集合中重复

  • productId

  • product

  • price

  • size

当应用程序显示订单信息时,它会显示相应的订单行项目。如果订单和产品信息存储在不同的集合中,则应用程序需要执行$lookup来连接两个集合中的数据。查找操作通常成本高昂且性能较差。

与仅将行项嵌入到orders集合相比,重复产品信息的原因是应用程序在显示订单时只需要产品信息的一个子集。通过仅嵌入所需字段,应用程序可以在不向orders集合添加不必要冗余的情况下存储额外的产品详细信息。

以下示例使用了子集模式来优化在线商店的访问模式。

考虑一个应用程序,当用户查看产品时,应用程序会显示产品的信息以及最近五条评论。这些评论存储在products集合和reviews集合中。

当写一条新评论时,会发生以下操作

  • 评论被插入到reviews集合。

  • 使用$pop$push更新products集合中最近评论的数组。

1
use productsAndReviews
2

productsAndReviews 数据库中创建以下集合

集合名称
描述
示例文档
products
存储产品信息。在 products 集合中的文档在 recentReviews 字段中嵌入最近五条产品评论。
db.products.insertOne( {
productId: 123,
name: "laptop",
price: 200,
recentReviews: [
{
reviewId: 456,
author: "Pat Simon",
stars: 4,
comment: "Great for schoolwork",
date: ISODate("2023-06-29")
},
{
reviewId: 789,
author: "Edie Short",
stars: 2,
comment: "Not enough RAM",
date: ISODate("2023-06-22")
}
]
} )
评论
存储所有产品的评论(不仅仅是最近评论)。在 reviews 集合中的文档包含一个 productId 字段,表示该评论针对的产品。
db.reviews.insertOne( {
reviewId: 456,
productId: 123,
author: "Pat Simon",
stars: 4,
comment: "Great for schoolwork",
date: ISODate("2023-06-29")
} )

应用程序只需要对数据库进行一次调用,就可以返回它需要显示的所有信息。如果数据完全存储在单独的集合中,应用程序需要连接来自 productsreviews 集合的数据,这可能会引起性能问题。

评论很少更新,因此存储重复数据并不昂贵,且在集合之间保持数据一致性不是挑战。

了解如何保持重复数据的一致性,请参阅数据一致性。

返回

操作因素