An application might need to derive a value from source data stored in a database. Computing a new value can require significant CPU resources, especially in the case of large data sets or in cases where multiple documents must be examined.应用程序可能需要从数据库中存储的源数据中获取值。计算新值可能需要大量的CPU资源,特别是在大型数据集或必须检查多个文档的情况下。
If a computed value is requested often, it can be more efficient to save that value in the database ahead of time. When the application requests data, only one read operation is required.如果经常请求计算值,则提前将该值保存在数据库中会更有效。当应用程序请求数据时,只需要一次读取操作。
About this Task关于此任务
If reads are significantly more common than writes, the computed pattern reduces the frequency of data computation. Instead of computing values on every read, the application stores the computed value and recalculates it as needed. The application can either recompute the value with every write that changes the computed value's source data, or as part of a periodic job.如果读取明显比写入更常见,则计算模式会降低数据计算的频率。应用程序存储计算值并根据需要重新计算,而不是在每次读取时计算值。应用程序可以在每次写入更改计算值的源数据时重新计算该值,也可以将其作为定期作业的一部分。
Note
With periodic updates, the returned computed value is not guaranteed to be exact. However, this approach may be worth the performance improvement if exact accuracy isn't a requirement.对于定期更新,无法保证返回的计算值是准确的。然而,如果不需要精确的精度,这种方法可能值得提高性能。
Steps步骤
In this example, an application displays movie viewer and revenue information. Users can look up a particular movie and how much money that movie made.在这个例子中,应用程序显示电影观众和收入信息。用户可以查找特定的电影以及该电影赚了多少钱。
Insert sample data插入示例数据
Create the 创建screenings collection: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
},
] )Insert computed data插入计算数据
Users often want to know how many people saw a certain movie and how much money that movie made. In the current schema, to add 用户经常想知道有多少人看过某部电影,这部电影赚了多少钱。在当前模式中,要添加num_viewers and revenue, you must perform a read for theaters that screened a movie with the title "Lost in the Shadows" and sum the values of those fields.num_viewers和revenue(收入),您必须对放映了标题为“迷失在阴影中”的电影的影院进行读取,并将这些字段的值相加。
To avoid performing that computation every time the information is requested, you can compute the total values and store them in a 为了避免每次请求信息时都执行该计算,您可以计算总值并将其与movies collection with the movie record itself:movies记录本身一起存储在电影集合中:
db.movies.insertOne(
{
_id: 1,
title: "Lost in the Shadows",
total_viewers: 1840,
total_revenue: 25880
}
)Updated computed data更新的计算数据
Consider a new screening is added to the 考虑在screenings collection: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
}
)
The computed data in the movies collection no longer reflects the current screening data. How often you update computed data depends on your application:movies集合中的计算数据不再反映当前的放映数据。更新计算数据的频率取决于应用程序:
In a low write environment, the computation can occur in conjunction with any update of the在低写环境中,计算可以与screeningsdata.screenings数据的任何更新同时进行。In an environment with more regular writes, the computations can be done at defined intervals (every hour for example). The source data in在具有更规则写入的环境中,可以按定义的间隔(例如每小时)进行计算。screeningsisn't affected by writes to themoviescollection, so you can run calculations at any time.screenings中的源数据不受写入电影集的影响,因此您可以随时运行计算。
To update the computed data based on the screenings data, you can run the following aggregation at a regular interval:要根据筛选数据更新计算数据,可以定期运行以下聚合:
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"
}
}
] )Results结果
The computed pattern reduces CPU workload and increases application performance. Consider the computed pattern your application performs the same calculations repeatedly and has a high read to write ratio.计算模式减少了CPU工作负载并提高了应用程序性能。考虑应用程序重复执行相同计算并具有高读写比的计算模式。