我们一般通过表达式$sum来计算总和。因为MongoDB的文档有数组字段,所以可以简单的将计算总和分成两种:1,统计符合条件的所有文档的某个字段的总和;2,统计每个文档的数组字段里面的各个数据值的和。这两种情况都可以通过$sum表达式来完成。以上两种情况的聚合统计,分别对应与聚合框架中的 $group 操作步骤和 $project 操作步骤。

1.$group

直接看例子吧。

Case 1

测试集合mycol中的数据如下:

  1. {
  2. title: 'MongoDB Overview',
  3. description: 'MongoDB is no sql database',
  4. by_user: 'runoob.com',
  5. url: 'http://www.runoob.com',
  6. tags: ['mongodb', 'database', 'NoSQL'],
  7. likes: 100
  8. },
  9. {
  10. title: 'NoSQL Overview',
  11. description: 'No sql database is very fast',
  12. by_user: 'runoob.com',
  13. url: 'http://www.runoob.com',
  14. tags: ['mongodb', 'database', 'NoSQL'],
  15. likes: 10
  16. },
  17. {
  18. title: 'Neo4j Overview',
  19. description: 'Neo4j is no sql database',
  20. by_user: 'Neo4j',
  21. url: 'http://www.neo4j.com',
  22. tags: ['neo4j', 'database', 'NoSQL'],
  23. likes: 750
  24. }

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算

  1. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])

查询结果如下:

  1. /* 1 */
  2. {
  3. "_id" : "Neo4j",
  4. "num_tutorial" : 1
  5. },
  6.  
  7. /* 2 */
  8. {
  9. "_id" : "runoob.com",
  10. "num_tutorial" : 2
  11. }

Case 2

统计每个作者被like的总和,计算表达式:

  1. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])

查询结果如下;

  1. /* 1 */
  2. {
  3. "_id" : "Neo4j",
  4. "num_tutorial" : 750
  5. },
  6.  
  7. /* 2 */
  8. {
  9. "_id" : "runoob.com",
  10. "num_tutorial" : 110
  11. }

Case 3

上面例子有些简单,我们再丰富一下,测试集合sales的数据如下:

  1. { "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
  2. { "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
  3. { "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
  4. { "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
  5. { "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }

需要完成的目标是,基于日期分组,统计每天的销售额,聚合公式为:

  1. db.sales.aggregate(
  2. [
  3. {
  4. $group:
  5. {
  6. _id: { day: { $dayOfYear: "$date"}, year: { $year: "$date" } },
  7. totalAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
  8. count: { $sum: 1 }
  9. }
  10. }
  11. ]
  12. )

查询结果是:

  1. { "_id" : { "day" : 46, "year" : 2014 }, "totalAmount" : 150, "count" : 2 }
  2. { "_id" : { "day" : 34, "year" : 2014 }, "totalAmount" : 45, "count" : 2 }
  3. { "_id" : { "day" : 1, "year" : 2014 }, "totalAmount" : 20, "count" : 1 }

Case 4

上面的,可以看出$group,我们都使用了_id,使用了分组,那么如果,我们的需求不需要分组,应该怎么办呢?

例如。我们现在要统计sales集合中一共卖出了多少件商品。

如果直接去掉group 阶段的_id,如下:

  1. db.sales.aggregate(
  2. [
  3. {
  4. $group:
  5. {
  6.  
  7. totalAmount: { $sum: "$quantity" }
  8. }
  9. }
  10. ]
  11. )

则报错:

  1. {
  2. "message" : "a group specification must include an _id",
  3. "ok" : 0,
  4. "code" : 15955,
  5. "codeName" : "Location15955",
  6. "name" : "MongoError"
  7. }

我们还是需要添加上_id,但是可以添加个常量,及时根据常量分组,可以为  _id : "0" 可以是   _id : "a",   _id : "b",   还可以使_id : "x",   _id : "y" 等等。

例如:

  1. db.sales.aggregate(
  2. [
  3. {
  4. $group:
  5. {
  6. _id : "Total"
  7. totalAmount: { $sum: "$quantity" }
  8. }
  9. }
  10. ]
  11. )

查询结果为:

  1. {
  2. "_id" : "Total",
  3. "totalAmount" : 28
  4. }

2.$project阶段

Case 5

假设存在一个 students 集合,其数据结构如下:

  1. { "_id": 1, "quizzes": [ 10, 6, 7 ], "labs": [ 5, 8 ], "final": 80, "midterm": 75 }
  2. { "_id": 2, "quizzes": [ 9, 10 ], "labs": [ 8, 8 ], "final": 95, "midterm": 80 }
  3. { "_id": 3, "quizzes": [ 4, 5, 5 ], "labs": [ 6, 5 ], "final": 78, "midterm": 70 }

现在的需求是统计每个学生的 平常的测验分数总和、实验分数总和、期末其中分数总和。

  1. db.students.aggregate([
  2. {
  3. $project: {
  4. quizTotal: { $sum: "$quizzes"},
  5. labTotal: { $sum: "$labs" },
  6. examTotal: { $sum: [ "$final", "$midterm" ] }
  7. }
  8. }
  9. ])

其查询输出结果如下:

  1. { "_id" : 1, "quizTotal" : 23, "labTotal" : 13, "examTotal" : 155 }
  2. { "_id" : 2, "quizTotal" : 19, "labTotal" : 16, "examTotal" : 175 }
  3. { "_id" : 3, "quizTotal" : 14, "labTotal" : 11, "examTotal" : 148 }

参考文献:

https://www.runoob.com/mongodb/mongodb-aggregate.html

https://docs.mongodb.com/manual/reference/operator/aggregation/sum/index.html

MongoDB 中聚合统计计算--$SUM表达式的更多相关文章

  1. MongoDB中聚合工具Aggregate等的介绍与使用

    Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY.聚合工具可以让开发人员直接使用MongoDB原生的命令操作数据库中的数据,并且按照要求进行聚合 ...

  2. 【翻译】MongoDB指南/聚合——聚合管道

    [原文地址]https://docs.mongodb.com/manual/ 聚合 聚合操作处理数据记录并返回计算后的结果.聚合操作将多个文档分组,并能对已分组的数据执行一系列操作而返回单一结果.Mo ...

  3. 在MongoDB中执行查询、创建索引

    1. MongoDB中数据查询的方法 (1)find函数的使用: (2)条件操作符: (3)distinct找出给定键所有不同的值: (4)group分组: (5)游标: (6)存储过程. 文档查找 ...

  4. MongoDB的聚合操作以及与Python的交互

    上一篇主要介绍了MongoDB的基本操作,包括创建.插入.保存.更新和查询等,链接为MongoDB基本操作. 在本文中主要介绍MongoDB的聚合以及与Python的交互. MongoDB聚合 什么是 ...

  5. MongoDB入门---聚合操作&管道操作符&索引的使用

    经过前段时间的学习呢,我们对MongoDB有了一个大概的了解,接下来就要开始使用稍稍深入一点的东西了,首先呢,就是MongoDB中的聚合函数,跟mysql中的count等函数差不多.话不多说哈,我们先 ...

  6. Mongodb的聚合和管道

    MongoDB 聚合 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果. aggregate() 方法 MongoDB中聚合的方法使用agg ...

  7. 关于MongoDB时间格式转换和时间段聚合统计的用法总结

    一 . 背景需求 在日常的业务需求中,我们往往会根据时间段来统计数据.例如,统计每小时的下单量:每天的库存变化,这类信息数据对运营管理很重要. 这类数据统计依赖于各个时间维度,年月日.时分秒都有可能. ...

  8. MongoDB中的聚合操作

    根据MongoDB的文档描述,在MongoDB的聚合操作中,有以下五个聚合命令. 其中,count.distinct和group会提供很基本的功能,至于其他的高级聚合功能(sum.average.ma ...

  9. MongoDB中的数据聚合工具Aggregate和Group

    周煦辰 2016-01-16 来说说MongoDB中的数据聚合工具. Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY.聚合工具可以让开发人员直 ...

随机推荐

  1. IPhone下json的解析 NSJSONSerialization

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Programming Lan ...

  2. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 Inp ...

  3. 最全的三剑客和linux正则符号讲解

    第2章 linux符号系列与三剑客    194 2.1 特殊符号系列    194 2.1.1 普通符号系列    194 2.1.2 引号符号系列    196 2.1.3 定向符号    197 ...

  4. django上传并显示图片

    环境 python 3.5 django 1.10.6 步骤 创建名为 testupload的项目 django-admin startproject testupload 在项目testupload ...

  5. Vue中兄弟组件间传值-(Bus/总线/发布订阅模式/观察者)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Python3、setuptools、Pip3安装详解

    Python3.setuptools.Pip3安装详解 2017年08月19日 18:58:47 安静的技术控 阅读数:26002    版权声明:本文为博主原创文章,未经博主允许不得转载. http ...

  7. Vue ---- 组价 组件化 子传父 父传子

    目录 补充js的for循环: 组件 1.组件的分类: 2.组件的特点 3.创建局部组件 4.全局组件 二.组件化 一.组件传参父传子 二.组件传参:子传父 补充js的for循环: // for in遍 ...

  8. Vue ---- vue的基本使用 文本/事件/属性指令 补充: js面向对象 js函数

    目录 日考题(知识点)

  9. Redis面试热点工程架构篇之数据同步

    温馨提示 更佳阅读体验:[决战西二旗]|Redis面试热点之工程架构篇[2] 前言 前面用了3篇文章介绍了一些底层实现和工程架构相关的问题,鉴于Redis的热点问题还是比较多的,因此今天继续来看工程架 ...

  10. zookeeper扫盲

    一.zookeeper概述 a.zookeeper是一个开源的分布式的项目,为分布式业务提供协调服务的apache顶级项目 那什么是分布式的呢,通俗的说就是多个机器可以同时去处理一件事情 b.zook ...