zoukankan      html  css  js  c++  java
  • 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" : "2018-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:

    有关$merge和可用选项的更多信息

    示例:按需物化视图:初始创建

    示例:按需物化视图:更新/替换数据

    示例:仅插入新数据

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

    译者:李正洋

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

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

  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/mongoing/p/15752349.html
Copyright © 2011-2022 走看看