注意
以下页面将讨论按需物化视图。 有关视图的讨论,请参阅视图。
从版本 4.2 开始,MongoDB 为聚合管道添加了 $merge阶段。 此阶段可以将管道结果合并到现有集合,而不是完全替换该集合。 此功能允许用户创建按需物化视图,其中输出collection的内容可以在每次管道运行时更新。
在 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 文档中的查看、过滤和排序文档。
例子
假定临近 2019 年 1 月底,集合 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. 定义按需物化视图
以下 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" } } ] ); };
2. 执行初始运行
对于初始运行,您可以传入值为 new
ISODate("1970-01-01") 的日期:
updateMonthlySales(new ISODate("1970-01-01"));
初次运行后,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. 刷新物化视图
假设到 2019 年 2 月的第一周,bakesales 集合用更新的销售信息进行更新,具体来说就是增加一月和二月的销售额。
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") } ] )
要刷新 1 月和 2 月的 monthlybakesales 数据,请再次运行该函数以重新运行聚合管道,并从 new ISODate("2019-01-01") 开始。
updateMonthlySales(new ISODate("2019-01-01"));
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") }
更多信息
$merge 阶段:
可以输出到相同或不同数据库中的集合。
如果输出集合不存在,则创建一个新集合。
可将结果(插入新文档、合并文档、替换文档、保留现有文档、操作失败、使用自定义更新管道处理文档)并入现有集合。
可输出到分片集合。输入集合也可以是分片的。
请参阅 $merge 以了解:
有关
$merge和可用选项的更多信息示例:按需物化视图:初始创建
示例:On-Demand Materialized View: Update/Replace Data(按需物化视图:更新/替换数据)
示例:Only Insert New Data(仅插入新数据)