Docs 菜单
Docs 主页
/
MongoDB Manual
/

处理重复数据

在此页面上

  • 关于此任务
  • 示例:电子商务架构中的重复数据
  • 步骤
  • 复制数据的好处
  • 示例:产品评价的重复数据
  • 步骤
  • 复制数据的好处
  • 了解详情

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

复制数据的一个问题是存储成本增加。但是,优化访问模式的好处通常大于存储的潜在增加成本。

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

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

  • 数据重复时,读取的性能优势。复制数据可以消除跨多个集合执行联接的需要,从而提高应用程序性能。

以下示例演示如何在电子商务应用程序模式中复制数据以改善数据访问和性能。

1
use eCommerce
2

eCommerce 数据库中创建以下集合:

集合名称
说明
文档样本

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 集合中。

当有新评论时,会发生以下写入操作:

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

存储产品的所有评论(不仅是最近的评论)。reviews 集合中的文档包含一个 productId 字段,该字段表示评论所涉及的产品。

db.reviews.insertOne( {
reviewId: 456,
productId: 123,
author: "Pat Simon",
stars: 4,
comment: "Great for schoolwork",
date: ISODate("2023-06-29")
} )

应用程序只需对数据库进行一次调用,即可返回它需要显示的所有信息。如果数据完全存储在单独的集合中,则应用程序将需要联接 productsreviews 集合中的数据,这可能会导致性能问题。

评论很少更新,因此存储重复数据的成本并不高,并且保持集合之间的数据一致性也不困难。

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

后退

操作因素