6

MongoDB按需物化视图介绍

 3 years ago
source link: https://mongoing.com/archives/81349
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

MongoDB按需物化视图介绍 | MongoDB中文社区

本页的内容讨论了按需物化视图。有关视图的讨论,请参阅视图

从4.2版本开始,MongoDB为aggregation pipeline添加了$merge阶段。此阶段可以将管道结果合并到现有集合中,而不是完全替换现有集合。此功能允许用户创建按需物化视图,每次运行管道时都可以更新输出集合的内容。

示例

假设现在接近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") },
] );

定义按需物化视图

下面的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" } }
   ] );
};
  • $match阶段过滤数据以仅处理那些销售额大于或等于startDate

  • 阶段按年-月对销售信息进行分组。此阶段输出的文档具有以下形式:

{ "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }
  • $merge阶段将输出写入到monthlybakesales集合

    基于on_id字段(未分片输出集合的默认值),此阶段会检查聚合结果中的文档是否 匹配 集合中的现有文档:

    • 当匹配时(即同年月的文档已经存在于集合中),此阶段会使用来自聚合结果的文档替换现有文档
    • 当不匹配时,此阶段将聚合结果中的文档插入到集合中(不匹配时的默认行为)。

执行初始运行

对于初始运行,你可以传入一个日期new ISODate("1970-01-01")

updateMonthlySales(new ISODate("1970-01-01"));

初始运行后,monthlybakesales包含以下文档;即db.monthlybakesales.find().sort( { _id: 1 } )返回以下内容:

{ "_id" : "018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : NumberDecimal("896") }

刷新物化视图

假设到了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

原文链接:https://docs.mongodb.com/manual/core/materialized-views/

译者:李正洋

DBA一枚,擅长oracle/mongodb//tidb等多种数据库。

现阶段对开源分布式数据库、云计算等领域有很大兴趣;平时喜欢打羽毛球、看电影等。

添加小芒果微信(ID:mongoingcom)进入中文用户组技术交流群。


Recommend

  • 243
    • 掘金 juejin.im 7 years ago
    • Cache

    教你用 css 写一个拟物化图标

    拟物化(Skeuomorphism)风格的图标在iOS7发布之前广为流行。相当长一段时间,无论系统、网页还是第三方应用都争相使用拟物化的设计风格。那时候的dribbble网,各色优秀的拟物化设计作品也争奇斗艳、层出不穷。 下面先展示几张优秀的拟物化设计作品,让

  • 28

    新拟物化最近被炒得很是火热,它会是2020年的UI设计趋势吗?本文作者从多个方面对此进行了分析,并总结了6种将新拟物化风格和其他风格相结合的设计方向,与大家分享。 我承认,为“这个激动人心的新趋势”共同命名(注:Neumorphism 新拟物化,即New和Sk

  • 12

    新拟物化 UI 设计(Neumorphism / soft ui)在近段时间流行起来的,我们在 Dribbble 中搜索 Neumorphism 就有很多相关的新拟物化设计作品,这种效果一眼看上去感觉很美,很舒服,但是怎么做出来的呢?今天设计达人分享这个 Neumorphism 在...

  • 49

    游戏陪玩市场,随着电竞蛋糕越做越大,规模也与日俱增,但陪玩中的灰色地带亦不少,往前一步就是万丈深渊。

  • 16

    大家有没有发现 Facebook 近期的改版也开始在扁平界面中加入了一些拟物化风格的元素。身为一名 UI、UX 设计师,也趁着这波疫情足不出户自我隔离期,一起加入了这挑起争端的行列,这篇文章会以改造的口罩 3.0 界面教大家怎么制作拟物化风格...

  • 16
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    Spark实践|物化视图在 SparkSQL 中的实践

    导言 物化视图作为一种预计算的优化方式,广泛应用于传统数据库中,如Oracle,MSSQL Server等。随着大数据技术的普及,各类数仓及查询引擎在业务中扮演着越来越重要的数据分析角色,而物化视图作为数据查询的加速器,将极大增...

  • 9

    ClickHouse性能优化?试试物化视图

  • 15

    TiFlink: 使用TiKV和Flink实现强一致的物化视图张茄子算法、 分布式技术和函数式编程爱好者

  • 9
    • timemachine.icu 2 years ago
    • Cache

    Doris 物化视图

    Doris 物化视图发表于2022-11-04更新于2022-11-04字数统计1.5k阅读时长8分阅读次数17648 物化视图(Materialized View)本质是一种预计算,即把某些耗时的操作(例如JOIN、AGGREGATE)的结果保存下来,以便在查...

  • 6

    PostgreSQL和Oracle物化视图比较 对于最终用户来说,物化视图基本上只是一个表,物化视图只是将结果

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK