应用程序可能需要从数据库中存储的源数据中获取值。 计算新值可能需要大量 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
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集合的影响,因此您可以随时运行计算。
要根据放映数据更新计算数据,您可以定期运行以下聚合:
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"       }    } ] ) 
结果
计算模式可减少 CPU工作负载并提高应用程序性能。 考虑应用程序重复执行相同计算并具有较高写入比率的计算模式。