按需物化视图是预先计算的聚合管道结果,它存储在磁盘上并从磁盘读取。按需物化视图通常是 或 $out 阶段的结果。
与标准视图的对比
MongoDB 提供两种不同的视图类型:标准视图和按需物化视图。这两种视图类型都可以返回聚合管道的结果。
索引
标准视图使用底层集合的索引。因此,您无法直接在标准视图上创建、删除或重新构建索引,也无法获取视图上的索引列表。
您可以直接在按需物化视图上创建索引,因为它们存储在磁盘中。
性能
按需物化视图的读取性能要优于标准视图,因为前者是从磁盘中读取,而不是作为查询的一部分通过计算得出。聚合管道越复杂,要聚合的数据量越大,这种性能优势就越明显。
在 MongoDB Atlas 用户界面中创建物化视图
本节中的示例使用示例训练数据集。要了解如何将示例数据集加载到您的 MongoDB Atlas 部署中,请参阅加载示例数据。
要在 MongoDB Atlas 用户界面中创建物化视图,请执行以下步骤:
在MongoDB Atlas用户界面中,转到项目的 Clusters 页面。
如果尚未显示,请从导航栏上的 Organizations 菜单中选择包含所需项目的组织。
如果尚未显示,请从导航栏的 Projects 菜单中选择您的项目。
在侧边栏中,单击 Database 标题下的 Clusters。
会显示集群页面。
添加 $out 阶段
从 Select 下拉菜单中选择
$out阶段。在聚合管道中添加以下事务语法,以将管道结果写入
sample_training数据库中的myView集合:'myView' 单击 Save Documents(连接)。
$out 阶段将 aggregation pipeline 的结果写入指定集合,由该集合创建视图。要了解更多信息,请参阅 $out。
刷新集合列表以查看 myView 集合。
要了解如何在 MongoDB Atlas 用户界面中查询 myView 集合,请参阅 MongoDB Atlas 文档中的查看、过滤和排序文档。
例子
该示例使用 sample_mflix 数据集中的 movies 集合。要了解如何加载示例数据,请参阅加载示例数据。
1. 定义按需物化视图
以下 updateMovieStats 函数定义了 movieYearStats 物化视图,其中包含按年份分类的电影的计数和平均 IMDb 评级。该函数接受 startYear 参数,用于更新从该年份发布的电影的统计信息。
updateMovieStats = function(startYear) { db.movies.aggregate( [ { $match: { year: { $gte: startYear } } }, { $group: { _id: "$year", movieCount: { $sum: 1 }, avgRating: { $avg: "$imdb.rating" } } }, { $merge: { into: "movieYearStats", whenMatched: "replace" } } ] ); };
2. 执行初始运行
对于初次运行,传入开始年份,以便使 movieYearStats 填充从该年份开始的数据:
updateMovieStats(2015);
初次运行后,db.movieYearStats.find().sort( { _id: 1 } ) 返回如下文档:
{ "_id" : 2015, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2016, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2017, "movieCount" : <num>, "avgRating" : <num> }
3. 刷新物化视图
假设向 2016 的 movies 集合添加了一部新电影:
db.movies.insertOne( { title: "Grove Test Movie", year: 2016, imdb: { rating: 7.5, votes: 500 } } )
要刷新 movieYearStats 以及后续的 2016,请以 startYear 为 2016 运行该函数:
updateMovieStats(2016);
更新的 movieYearStats 反映了 movies 集合中的新电影。db.movieYearStats.find().sort( { _id: 1 } ) 返回:
{ "_id" : 2015, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2016, "movieCount" : <num>, "avgRating" : <num> } { "_id" : 2017, "movieCount" : <num>, "avgRating" : <num> }
更多信息
$merge 阶段:
可以输出到相同或不同数据库中的集合。
如果输出集合不存在,则创建一个新集合。
可将结果(插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档)并入现有集合。
可输出到分片集合。输入集合也可以是分片的。
请参阅 $merge 以了解:
有关
$merge和可用选项的更多信息示例:按需物化视图:初始创建
示例:On-Demand Materialized View: Update/Replace Data(按需物化视图:更新/替换数据)
示例:Only Insert New Data(仅插入新数据)