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

存储计算数据

本页

  • 关于此任务
  • 步骤
  • 结果
  • 了解更多

应用程序可能需要从数据库中存储的源数据中派生一个值。计算新值可能需要大量的CPU资源,尤其是在大型数据集或需要检查多个文档的情况下。

如果经常请求计算的值,预先将其保存到数据库中会更有效率。当应用程序请求数据时,只需进行一次读取操作。

如果读取操作远多于写入操作,这种计算模式可以降低数据计算的频率。应用程序不需要在每次读取时都计算值,而是将计算值存储起来,并在需要时重新计算。应用程序可以选择在更改计算值源数据的每次写入时重新计算值,或者作为周期性任务的一部分。

注意

使用周期性更新,返回的计算值不一定保证是准确的。然而,如果不需要精确度,这种方法可能值得为了性能改进。

在此示例中,应用程序显示电影观众和收入信息。用户可以查找特定的电影以及该电影赚了多少钱。

1

创建screenings 集合

db.screenings.insertMany( [
{
theater: "Alger Cinema",
location: "Lakeview, OR",
movie_title: "Lost in the Shadows",
movie_id: 1,
num_viewers: 344,
revenue: 3440
},
{
theater: "City Cinema",
location: "New York, NY",
movie_title: "Lost in the Shadows",
movie_id: 1,
num_viewers: 1496,
revenue: 22440
},
] )
2

用户通常想知道有多少人看过某部电影以及这部电影赚了多少钱。在当前模式中,为了添加 num_viewersrevenue,您必须读取具有标题“失落的阴影”的影院,并计算这些字段的值。

为了避免每次请求信息时都执行该计算,您可以计算总值并将它们存储在包含电影记录本身的 movies 集合中

db.movies.insertOne(
{
_id: 1,
title: "Lost in the Shadows",
total_viewers: 1840,
total_revenue: 25880
}
)
3

考虑向 screenings 集合中添加新的放映

db.screenings.insertOne(
{
theater: "Overland Park Cinema",
location: "Boise, ID",
movie_title: "Lost in the Shadows",
movie_id: 1,
num_viewers: 760,
revenue: 7600
}
)

movies 集合中的计算数据不再反映当前的放映数据。计算数据的更新频率取决于您的应用程序

  • 在低写环境下,计算可以在与 screenings 数据的任何更新一起进行。

  • 在写操作更频繁的环境中,计算可以在定义的间隔内进行(例如每小时一次)。在screenings中的源数据不受对movies集合的写操作的影响,因此您可以随时运行计算。

要基于screenings数据更新计算数据,您可以定期运行以下聚合操作:

db.screenings.aggregate( [
{
$group: {
_id: "$movie_id",
total_viewers: {
$sum: "$num_viewers"
},
total_revenue: {
$sum: "$revenue"
}
}
},
{
$merge: {
into: { db: "test", coll: "movies" },
on: "_id",
whenMatched: "merge"
}
}
] )
4

要确认movies集合是否已更新,查询该集合:

db.movies.find()

输出

[
{
_id: 1,
title: 'Lost in the Shadows',
total_viewers: 2600,
total_revenue: 33480
}
]

计算模式可以减少CPU负载并提高应用程序性能。考虑计算模式时,您的应用程序执行相同的计算多次,并且具有高读/写比。

  • 使用近似模式

  • 分组数据

  • 数据一致性

返回

计算值