当前播放: 09 | 实验:聚合查询
00:00 / 00:00
高清
  • 高清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看
课程目录
第一章:MongoDB再入门 (12讲)
01 | 课程介绍
免费
02 | 内容综述
免费
03 | 认识文档数据库MongoDB
免费
04 | MongoDB特色及优势
免费
05 | 实验:安装MongoDB
免费
06 | MongoDB基本操作
07 | 实验:Hello World程序开发
08 | 聚合查询
09 | 实验:聚合查询
10 | 复制集机制及原理
11 | 实验:搭建MongoDB复制集
12 | MongoDB全家桶
第二章:从熟练到精通的开发之路 (12讲)
13 | 模型设计基础
14 | JSON文档模型设计特点
15 | 文档模型设计之一:基础设计
16 | 文档模型设计之二:工况细化
17 | 文档模型设计之三:模式套用
18 | 设计模式集锦
19 | 事务开发:写操作事务
20 | 事务开发:读操作事务之一
21 | 事务开发:读操作事务之二
22 | 事务开发:多文档事务
23 | Change Stream
24 | MongoDB开发最佳实践
09 | 实验:聚合查询

09 | 实验:聚合查询

唐建法(TJ)
Tapdata CTO、MongoDB中文社区主席、前MongoDB大中华区首席架构师
47讲 约500分钟3451
单独订阅¥129
2人成团¥99
5
登录 后留言

精选留言(26)

  • 旺旺
    一口气刷到这里,老师讲的清晰明了,听的很过瘾!
    2019-11-13
    7
  • JAJAJA
    我们业务场景就遇到了聚合查询的情况,很简单,但是对于小白也很费脑筋。作为网关流量统计需求,接口需要给前端返回每日00:00:00 ~ 23:59:59这一天内,字段messageType分别为01 02 03 04 ,四种业务意义的请求数量,请老师明示怎么动态取每天的date,然后返回的结果分条显示当天24小时之内,不同值messageType得请求数量count(messageType)。

    作者回复: 这个问题需要一些时间,所以回复晚了一点。


    ## 数据模型

    测试数据:

    ```javascript
    db.test.insertMany([
        {
            messageType: '01',
            date: ISODate("2019-01-01T01:15:42Z")
            // 其他字段
        },
        {
            messageType: '01',
            date: ISODate("2019-01-01T01:17:42Z")
        },
        {
            messageType: '02',
            date: ISODate("2019-01-17T01:17:42Z")
        },
        {
            messageType: '02',
            date: ISODate("2019-01-17T02:17:42Z")
        },
    ])
    ```
    ## 解决思路

    1. 从日期中提取日期和小时。这里如果有必要,需要考虑时区问题。如果考虑时区问题,则需要3.6以上版本支持;
    1. 按日期、小时分组聚合;

    使用到的运算符:

    - [$dateToString](https://docs.mongodb.com/manual/reference/operator/aggregation/dateToString/)
    - [$year](https://docs.mongodb.com/manual/reference/operator/aggregation/year/)
    - [$month](https://docs.mongodb.com/manual/reference/operator/aggregation/month/)
    - [$dayOfMonth](https://docs.mongodb.com/manual/reference/operator/aggregation/dayOfMonth/)

    ## 聚合语句

    ```javascript
    db.test.aggregate([
        // 过滤条件(如果有)
        {
            $match: {
                date: {
                    $gte: ISODate("2019-01-01T00:00:00Z"),
                    $lt: ISODate("2019-02-01T00:00:00Z"),
                }
            }
        },
        // 映射出日期和小时
        {
            $project: {
                date: {
                    $dateToString: {
                        date: "$date",
                        format: "%Y-%m-%d",
                        timezone: "+08:00"
                    }
                },
                hour: {
                    $hour: "$date"
                },
                messageType: 1
            }
        },
        {
            // 按日期、小时、messageType分组计数
            $group: {
                _id: {
                    date: "$date",
                    hour: "$hour",
                    messageType: "$messageType"
                },
                count: {
                    $sum: 1
                }
            }
        }
    ]);
    ```

    2019-11-13
    7
  • fedwing
    还有一个小建议,希望老师更多讲讲为什么这么设计,内部实现原理,方便真正理解mongo,而不只是会用!目前我在国内一线游戏大厂开发一款算是爆款的游戏,随着游戏数据的增多,暴露出一些mongo问题,用的是3.2的mongo,且没有切wt,目前想要调整版本和存储引擎,所以想要深入了解mongo,想要成为mongo高手,期待老师赶紧更新

    作者回复: 谢谢。后续章节会涉及一些设计方面的。但是本课程的目标确实是偏应用方面多一点。源码底层内容太多,可能需要另外的课程来覆盖。

    2019-11-15
    5
  • 唐朝农民
    老师问个实际使用中有点纠结的问题,你的DEMO 中,很多数据基本上都是冗余存储到一个collection上面,比如 订单中的商品或国家直接存储的是对应的名称,而我们使用MySql 时通常存储的是 对应的ID,这样mysql 的查询往往需要join 多张表才能满足用户的查询需求,mongo 这样的冗余存储则不需要,但是这也带来一个问题,就是数据一致性问题,当我需要修改某个商品的名称时对应该商品的所有关联数据都要修改,如果像关系型数据库那样主外键设计,那可能还是需要先设计好对应表之间的关系,并且查询同样要聚合查询,那岂不又失去了MongoDb 的文档灵活性,相比mysql还有那么大的优势吗?目前我们项目中只有类似日志这样永远不会变的数据用的MongoDB存储,还请老师解答我的疑惑

    作者回复: 你可以打破常规思维考虑。国家的名称你多长时间需要改一次呢?当然,商品名称修改频率会略高一些,但也是低频动作。MongoDB已经提供多表多行事务来保证修改的一致性。另外如果是经常要改的内容,也还是可以按照关系设计,并不是绝对要放到一张表里面。

    2019-11-14
    4
  • vachel
    老师,感谢精彩的分享!请教一下聚合查询的性能问题,能否结合您的业务场景自己数据量说明一下 ?非常感谢!

    作者回复: 这个范围很广。我们的客户中最大的有100TB的数据量上做聚合的(Amadeus)。当然那个是32台物理服务器和288个微分片的架构,比较复杂了。

    通常来说MongoDB有可以在内存做计算的特性,如果你可以把你的数据都放在内存,那么聚合运算的性能大概率可以不错。

    如果你有数千万数亿以上的行数要做扫描性汇聚,又是跑在机械盘,索引又没有优化,那么有可能是分钟级的聚合计算性能。

    2019-11-13
    2
    2
  • JAJAJA
    Mongo Compass官方的就是好用,大而全,我们还在用Mongo Booster,Mongo Compass中的Export To Language,帮我解决了大问题,在Mysql聚合查询语句翻译成MQL,再转换成Java 方式,快速高效,不用去翻MongoaTemplate API了.

    作者回复: 非常棒!

    2019-11-13
    2
  • 老师请问下,如果我有若干年的毫秒级的价格数据,我想对每条数据增加一个字段,字段内容为当前时间到接下来1000毫秒之间的数据的价格字段的最大值,怎么实习呢?

    作者回复: MongoDB里面貌似实现不了这么高级的计算,可能只能拉到内存里。这么大的量的话,要用到spark来做并发计算然后再把结果写回去mongodb。

    2019-11-28
    1
    1
  • 齐宝金
    老师好,请问下对于:
    rs1:PRIMARY> db.oplog.rs.findOne().ts
    Timestamp(1574326231, 1)

    执行db.oplog.rs.findOne().ts 时,返回值是Timestamp(1574326231, 1)。而我的需求是指获取1574326231,如果想获取1574326231值,有现成的函数吗,还是自己解析

    作者回复: > Timestamp(1574326231, 1).getTime()
    157432623

    2019-11-21
    1
    1
  • Calvin
    TJ大,能说下Mongo的存储引擎索引是采用B+树还是B-树存储的吗? 网上一般都是说B-树 也有一哥们儿说问过WireTiger的作者是B+树 个人觉得B+树更合理些 如果真的是B-树 能否给解释下why呢? 感谢

    作者回复: 你先说说看为什么B+树更合理,我在回复你 ;-)

    2019-11-18
    2
    1
  • 确认过眼神
    老师,每周更新三节吗?一共多少节?配那本教材一起看会更全面一些?

    作者回复: 视频课程提供课件,其他更多的内容可以去到docs.mongodb.com 上面有很详尽的参考。如果对某些地方不是很理解可以提问。

    2019-11-16
    1
  • fedwing
    一口气把所有视频看完了,意犹未尽,期待老师的新视频
    2019-11-14
    1
  • 浓烈
    老师,怎么按照时间间隔查询数据呢?现在我们用mongodb存储的物联网数据,数据量大,数据之间的时间间隔不确定,有可能1秒1条,有可能3秒1条。假如现在有1千万条这样的数据,怎么按照1分钟的时间间隔快速查询?查询出来的数据间的时间间隔大约为1分钟就行。现在工作中遇到这个问题,页面需要按自定义的时间间隔展示这些数据,不知道有没有比较好的解决方案
    2019-12-23
  • YoKate
    我的数据库某张表有2.2M的数据,我需要从这些数据里面计算出想要的数据,比如某个产品的销售额度。这个用聚合会把数据库查崩么》

    作者回复: 这么没信心。。。

    如果计算的结果太大, 超过16MB,或者需要在内存进行排序或其他计算的时候超过100MB,聚合操作会失败。通常的做法是避免对非索引字段进行排序,或者使用allowDiskUse选项来突破100MB的限制。

    另外,考虑在从节点上进行这样的聚合操作。否则会影响其他的数据库操作业务。

    2019-12-16
  • 风中花
    {
            "InputTime":{
            $gte:ISODate("2019-11-30"),
         $lte:ISODate('2019-12-05')
            }
    }

    老师好,在compass 里面match 执行脚本查不出数据。我把脚本放到robo 执行可以查到数据。

    请老师解惑,目前不知道什么原因?

    作者回复: 可能需要看你的数据,及实际的输出。这个条件看上去没什么问题

    2019-12-04
  • 做聚合查询,希望把多个文档的同一字段合并在一起,这样使用第三方工具(matlab)读取时速度会明显加快,聚合过程中出现了BufBuilder attempted to grow() to 67108868 bytes, past the 64MB limit.' 在网上查了下说是mongodb单个文档的大小限制。一般遇到这个问题该这么处理呢?感觉分成多个文档虽然可行但违背想方便的读取数据这个使用初衷了呢

    作者回复: 这个是MongoDB的物理限制,目前除了分文档之外没有别的解决方案。

    2019-11-30
  • 蓝魔丶
    老师有一个现在遇到的业务场景问题:同步的气象数据中有个data字段是二维数组地理坐标位置,比如:data [[101,23][102,32]],有另外一个geo多边形表示范围,判断现在data中哪些数据在多边形范围之内,我也看了mongodb对于geo索引查询的支持,比如:
    var poly1=db.storePolygon.findOne();
    db.storePoint.find({ "location" : { "$geoWithin" : { "$geometry" : poly1.geometry1 } } })
    这样的形式要求storePoint集合的每条数据都是单个坐标点,无法适配气象数据data字段包含所有点的情况,请问要怎么编写才合理?
    2019-11-27
  • Julien
    compass的export to language 没有C++吗?

    作者回复: 目前还不支持

    2019-11-24
  • 忘记、时间
    老师,我们因为业务需要,需要关键查询,聚合查询的时候,lookup后非常慢,这个有什么办法解决么?

    作者回复: 这个需要你提供具体的查询语句。可以加上explain,如:

    db.orders.explain().aggregate( [...])

    然后看看是什么样的慢

    2019-11-21
    1
  • 奔奔奔跑
    老师您好,我正在用mongodb,但是使用过程中发现了一个很奇怪的问题,我把查询语句贴上来。
    db.rooms.find({"staffid": ObjectId("5d37b78d864a61330babd2c5"), "status": "离线" })可以命中索引,返回文档1570
    db.rooms.aggregate({ $match: { "staffid": ObjectId("5d37b78d864a61330babd2c5"), "status": "离线" } },
    { $sort: { "createat": -1 } },
    { $skip: 10 },
    { $limit: 30 },
    命中索引,但是却是全表(24万)扫描了。这是为什么呢,find和aggregate的match不一样吗?

    作者回复: 你在你的find 里面加上同样的sort试试。

    2019-11-21
    2
  • 肖大保健
    老师
    实验四:地区销量top1
    这个例子 如果我只取每个区域sku销量最大的那个返回该怎么写

    作者回复: 假设数据模型是:

    ```javascript
    db.testData.insertMany([{
        areaCode: "Shanghai",
        sales: 100
    }, {
        areaCode: "Beijing",
        sales: 120
    }, {
        areaCode: "Shenzhen",
        sales: 130
    }, {
        areaCode: "Shenzhen",
        sales: 120
    }, {
        areaCode: "Shenzhen",
        sales: 100
    }, {
        areaCode: "Beijing",
        sales: 100
    }]);
    ```

    要计算每个地区的top1,需要将数据按照地区和销量排序,然后取每个分组(即每个地区)的`$first`:

    ```javascript
    db.testData.aggregate([{
        $sort: {
            areaCode: 1,
            sales: -1
        }
    }, {
        $group: {
            _id: "$areaCode",
            topSales: {
                $first: "$sales"
            }
        }
    }]);
    ```

    参考:

    - `$first`: https://docs.mongodb.com/manual/reference/operator/aggregation/first/
    - `$group`: https://docs.mongodb.com/manual/reference/operator/aggregation/group/

    2019-11-20
收起评论
看过的人还看
MySQL实战45讲

林晓斌  网名丁奇,前阿里资深技术专家

48讲 | 43741 人已学习

拼团 ¥69 原价 ¥99
Elasticsearch核心技术与实战

阮一鸣  eBay Pronto平台技术负责人

100讲 | 16796 人已学习

拼团 ¥89 原价 ¥129
设计模式之美

王争  前Google工程师,《数据结构与算法之美》专栏作者

100讲 | 18080 人已学习

拼团 ¥129 原价 ¥199
后端技术面试38讲

李智慧  同程艺龙交通首席架构师,前Intel&阿里架构师,《大型网站技术架构》作者

38讲 | 3711 人已学习

拼团 ¥79 原价 ¥99