On-Demand Materialized Views按需物化视图
On this page本页内容
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它们使用$merge
or$out
stage to update the saved data.$merge
或$out
阶段来更新保存的数据。
Indexes索引
Standard views use the indexes of the underlying collection. 标准视图使用基础集合的索引。As a result, you cannot create, drop or re-build indexes on a standard view directly, nor get a list of indexes on the view.因此,您无法直接在标准视图上创建、删除或重新构建索引,也无法获取视图上的索引列表。
You can create indexes directly on on-demand materialized views because they are stored on disk.您可以直接在按需具体化视图上创建索引,因为它们存储在磁盘上。
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.这种性能优势随着管道的复杂性和聚合数据的大小而增加。
Example实例
Assume near the end of January 2019, the collection 假设在2019年1月底,集合bakesales
contains the sales information by items:bakesales
包含按项目列出的销售信息:
db.bakesales.insertMany( [
{ date: new ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("90") },
{ date: new ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: new NumberDecimal("200") },
{ date: new ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: new NumberDecimal("12") },
{ date: new ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
] );
1. Define the On-Demand Materialized View定义按需物化视图
The following 下面的updateMonthlySales
function defines a monthlybakesales
materialized view that contains the cumulative monthly sales information. updateMonthlySales
函数定义了一个包含累计月度销售信息的monthlybakesales
物化视图。In the example, the function takes a date parameter to only update monthly sales information starting from a particular date.在本例中,该函数使用日期参数仅更新从特定日期开始的每月销售信息。
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$match
stage filters the data to process only those sales greater than or equal to thestartDate
.$match
阶段筛选数据以仅处理那些大于或等于startDate
的销售额。The$group
stage groups the sales information by the year-month.$group
阶段按年度月份对销售信息进行分组。The documents output by this stage have the form:此阶段输出的文档具有以下形式:{ "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }
The$merge
stage writes the output to themonthlybakesales
collection.$merge
阶段将输出写入monthlybakesales
集合。Based on the基于_id
field (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" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : NumberDecimal("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: new ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: new NumberDecimal("90") },
{ date: new ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: new NumberDecimal("32") },
{ date: new ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: new NumberDecimal("24") },
{ date: new ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: new NumberDecimal("8") },
{ date: new ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("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" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 102, "sales_amount" : NumberDecimal("1142") }
{ "_id" : "2019-02", "sales_quantity" : 15, "sales_amount" : NumberDecimal("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有关$merge
and available options$merge
和可用选项的详细信息Example:示例:On-Demand Materialized View: Initial Creation按需物化视图:初步创建Example:示例:On-Demand Materialized View: Update/Replace Data按需物化视图:更新/替换数据Example:示例:Only Insert New Data仅插入新数据