Note
Disambiguation消歧
This page discusses on-demand materialized views. For discussion of standard views, see Views.本页讨论按需物化视图。有关标准视图的讨论,请参阅视图。
To understand the differences between the view types, see Comparison with Standard Views.要了解视图类型之间的差异,请参阅与标准视图的比较。
An on-demand materialized view is a pre-computed aggregation pipeline result that is stored on and read from disk. On-demand materialized views are typically the results of a 按需物化视图是存储在磁盘上并从磁盘读取的预先计算的聚合管道结果。按需物化视图通常是$merge or $out stage.$merge或$out阶段的结果。
Comparison with Standard Views与标准视图的比较
MongoDB provides two different view types: standard views and on-demand materialized views. Both view types return the results from an aggregation pipeline.MongoDB提供了两种不同的视图类型:标准视图和按需物化视图。这两种视图类型都返回聚合管道的结果。
Standard views are computed when you read the view, and are not stored to disk.标准视图是在您读取视图时计算的,不会存储到磁盘上。On-demand materialized views are stored on and read from disk. They use a按需物化视图存储在磁盘上并从磁盘读取。他们使用$mergeor$outstage to update the saved data.$merge或$out阶段来更新保存的数据。Note
When using使用$merge, you can use change streams to watch for changes on the materialized view. When using$out, you can't watch for changes on the materialized view.$merge时,您可以使用更改流来监视物化视图上的更改。使用$out时,您无法观察物化视图上的变化。
Indexes索引
Standard views use the indexes of the underlying collection. As a result, you cannot create, drop or re-build general indexes on a standard view directly, nor get a list of general indexes on the view.标准视图使用基础集合的索引。因此,您无法直接在标准视图上创建、删除或重新构建常规索引,也无法在视图上获取常规索引列表。
MongoDB stores search indexes and vector search indexes on disk. Accordingly, you can create MongoDB Search indexes and Vector Search indexes on compatible views that contain only the following stages:MongoDB在磁盘上存储搜索索引和矢量搜索索引。因此,您可以在仅包含以下阶段的兼容视图上创建MongoDB搜索索引和矢量搜索索引:
$addFields$set$matchwrapping an包装了$exproperation操作
You can also create indexes directly on on-demand materialized views because MongoDB stores those indexes on disk.您还可以直接在按需物化视图上创建索引,因为MongoDB将这些索引存储在磁盘上。
Performance性能
On-demand materialized views provide better read performance than standard views because they are read from disk instead of computed as part of the query. This performance benefit increases based on the complexity of the pipeline and size of the data being aggregated.按需物化视图提供了比标准视图更好的读取性能,因为它们是从磁盘读取的,而不是作为查询的一部分计算的。这种性能优势会随着管道的复杂性和聚合数据的大小而增加。
Create a Materialized View in the MongoDB Atlas UI在MongoDB Atlas UI中创建物化视图
The example in this section uses the sample training dataset. To learn how to load the sample dataset into your MongoDB Atlas deployment, see Load Sample Data.本节中的示例使用示例训练数据集。要了解如何将示例数据集加载到MongoDB Atlas部署中,请参阅加载示例数据。
To create a materialized view in the MongoDB Atlas UI, follow these steps:要在MongoDB Atlas UI中创建物化视图,请执行以下步骤:
In the MongoDB Atlas UI, go to the Clusters page for your project.在MongoDB Atlas UI中,转到项目的“集群”页面。
Warning
Navigation Improvements In Progress导航改进正在进行中
We're currently rolling out a new and improved navigation experience. If the following steps don't match your view in the Atlas UI, see the preview Atlas documentation.我们目前正在推出一种新的、改进的导航体验。如果以下步骤与Atlas UI中的视图不匹配,请参阅Atlas预览文档。
If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.如果尚未显示,请从导航栏的“组织”菜单中选择包含所需项目的组织。If it's not already displayed, select your project from the Projects menu in the navigation bar.如果尚未显示,请从导航栏中的“项目”菜单中选择您的项目。If it's not already displayed, click Clusters in the sidebar.如果尚未显示,请单击侧栏中的“集群”。
The Clusters page displays.将显示“群集”页面。
Navigate to the collection导航到集合
For the cluster that contains the sample data, click Browse Collections.对于包含示例数据的集群,单击“浏览集合”。In the left navigation pane, select the sample_training database.在左侧导航窗格中,选择“sample_training”数据库。Select the grades collection.选择grades集合。
Select an aggregation stage from the Select drop-down menu从“选择”下拉菜单中选择聚合阶段
The aggregation stage transforms the data that you want to save as a view. To learn more about available aggregation stages, see Aggregation Stages.聚合阶段转换要另存为视图的数据。要了解有关可用聚合阶段的更多信息,请参阅聚合阶段。
For this example, add a new field with the 对于此示例,使用$set stage:$set阶段添加一个新字段:
Select从“选择”下拉菜单中选择$setfrom the Select drop-down menu.$set。Add the following syntax to the aggregation pipeline editor to create an average score across all将以下语法添加到聚合管道编辑器中,以创建scorevalues in thescoresarray within thegradescollection:grades(成绩)集合中scores数组中所有score(分数)值的平均分数:{
averageScore: { $avg: "$scores.score" }
}MongoDB Atlas adds theMongoDB Atlas将averageScorevalue to each document.averageScore值添加到每个文档中。
Add the $out stage添加$out阶段
$out stageSelect the从“选择”下拉菜单中选择$outstage from the Select drop-down menu.$out阶段。Add the following syntax to the aggregation pipeline to write the results of the pipeline to the将以下语法添加到聚合管道中,以将管道的结果写入myViewcollection in thesample_trainingdatabase:sample_training数据库中的myView集合:'myView'Click Save Documents.单击“保存文档”。
The $out stage writes the results of the aggregation pipeline to the specified collection, which creates the view. To learn more, see $out.$out阶段将聚合管道的结果写入指定的集合,从而创建视图。要了解更多信息,请参阅$out。
Refresh the list of collections to see the 刷新集合列表以查看myView collection.myView集合。
To learn how to query the 要了解如何在MongoDB Atlas UI中查询myView collection in the MongoDB Atlas UI, see View, Filter, and Sort Documents in the MongoDB Atlas documentation.myView集合,请参阅MongoDB Atlas文档中的查看、筛选和排序文档。
Example示例
Assume near the end of January 2019, the collection 假设在2019年1月底左右,集合bakesales contains the sales information by items:bakesales(烘焙品)包含按商品分类的销售信息:
db.bakesales.insertMany( [
{ date: ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: Decimal128("60") },
{ date: ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: Decimal128("90") },
{ date: ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: Decimal128("200") },
{ date: ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: Decimal128("80") },
{ date: ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: Decimal128("16") },
{ date: ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: Decimal128("60") },
{ date: ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: Decimal128("60") },
{ date: ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: Decimal128("16") },
{ date: ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") },
{ date: ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: Decimal128("48") },
{ date: ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: Decimal128("36") },
{ date: ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") },
{ date: ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: Decimal128("20") },
{ date: ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: Decimal128("80") },
{ date: ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: Decimal128("12") },
{ date: ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: Decimal128("48") },
{ date: ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: Decimal128("36") },
{ date: ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") },
{ date: ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: Decimal128("80") },
{ date: ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: Decimal128("60") },
{ date: ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") },
] );1. Define the On-Demand Materialized View定义按需物化视图
The following 以下updateMonthlySales function defines a monthlybakesales materialized view that contains the cumulative monthly sales information. In the example, the function takes a date parameter to only update monthly sales information starting from a particular date.updateMonthlySales函数定义了一个包含累积月度销售信息的monthlybakesales物化视图。在该示例中,该函数采用日期参数,仅更新从特定日期开始的每月销售信息。
updateMonthlySales = function(startDate) {
db.bakesales.aggregate( [
{ $match: { date: { $gte: startDate } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m", date: "$date" } }, sales_quantity: { $sum: "$quantity"}, sales_amount: { $sum: "$amount" } } },
{ $merge: { into: "monthlybakesales", whenMatched: "replace" } }
] );
};
The$matchstage filters the data to process only those sales greater than or equal to thestartDate.$match阶段筛选数据,仅处理大于或等于startDate的销售。The$groupstage groups the sales information by the year-month. The documents output by this stage have the form:$group阶段按年月对销售信息进行分组。此阶段输出的文档具有以下形式:{ "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }The$mergestage writes the output to themonthlybakesalescollection.$merge阶段将输出写入monthlybakesales集合。Based on the根据_idfield (the default for unsharded output collections), the stage checks if the document in the aggregation results matches an existing document in the collection:_id字段(未记录输出集合的默认值),该阶段检查聚合结果中的文档是否与集合中的现有文档匹配:When there is a match (i.e. a document with the same year-month already exists in the collection), the stage replaces the existing document with the document from the aggregation results.当存在匹配时(即集合中已存在具有相同年月的文档),该阶段将用聚合结果中的文档替换现有文档。When there is not a match, the stage inserts the document from the aggregation results into the collection (the default behavior when not matched).当不匹配时,该阶段会将聚合结果中的文档插入到集合中(不匹配时的默认行为)。
2. Perform Initial Run执行初始运行
For the initial run, you can pass in a date of 对于首次运行,您可以传入日期new ISODate("1970-01-01"):new ISODate("1970-01-01"):
updateMonthlySales(new ISODate("1970-01-01"));After the initial run, the 初次运行后,monthlybakesales contains the following documents; i.e. db.monthlybakesales.find().sort( { _id: 1 } ) returns the following:monthlybakesales(月度烘焙产品)包含以下文件:;即db.monthlybakesales.find().sort( { _id: 1 } )返回以下结果:
{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : Decimal128("506") }
{ "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : Decimal128("896") }3. Refresh Materialized View刷新物化视图
Assume that by the first week in February 2019, the 假设到2019年2月的第一周,bakesales collection is updated with newer sales information; specifically, additional January and February sales.bakesales集合已更新为新的销售信息;特别是1月和2月的额外销售。
db.bakesales.insertMany( [
{ date: ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: Decimal128("90") },
{ date: ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: Decimal128("32") },
{ date: ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: Decimal128("20") },
{ date: ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: Decimal128("24") },
{ date: ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: Decimal128("40") },
{ date: ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: Decimal128("40") },
{ date: ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") },
{ date: ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: Decimal128("8") },
{ date: ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: Decimal128("60") },
{ date: ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: Decimal128("16") },
{ date: ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: Decimal128("100") }
] )To refresh the 要刷新1月和2月的monthlybakesales data for January and February, run the function again to rerun the aggregation pipeline, starting with new ISODate("2019-01-01").monthlybakesales(月度烘焙销售)数据,请再次运行该函数以重新运行聚合管道,从new ISODate("2019-01-01")开始。
updateMonthlySales(new ISODate("2019-01-01"));The content of monthlybakesales has been updated to reflect the most recent data in the bakesales collection; i.e. db.monthlybakesales.find().sort( { _id: 1 } ) returns the following:monthlybakesales的内容已经更新,以反映bakesales集合中的最新数据;即db.monthlybakesales.find().sort( { _id: 1 } )返回以下结果:
{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : Decimal128("506") }
{ "_id" : "2019-01", "sales_quantity" : 102, "sales_amount" : Decimal128("1142") }
{ "_id" : "2019-02", "sales_quantity" : 15, "sales_amount" : Decimal128("284") }Additional Information附加信息
Can output to a collection in the same or different database.可以输出到相同或不同数据库中的集合。Creates a new collection if the output collection does not already exist.如果输出集合不存在,则创建新集合。Can incorporate results (insert new documents, merge documents, replace documents, keep existing documents, fail the operation, process documents with a custom update pipeline) into an existing collection.可以将结果(插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档)合并到现有集合中。Can output to a sharded collection. Input collection can also be sharded.可以输出到分片集合。输入集合也可以分片。
More information on有关$mergeand available options$merge和可用选项的更多信息Example:示例:On-Demand Materialized View: Initial Creation按需物化视图:初步创建Example:示例:On-Demand Materialized View: Update/Replace Data按需物化视图:更新/替换数据Example:示例:Only Insert New Data仅插入新数据