惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - Nucky_yang

windows系统下安装openclaw,无权限打开软件,无权限打开浏览器,无权限读写文件的问题。 just a demo presto集成 hive(转载) java可重入锁与不可重入锁 的设计 动态规划 背包问题 java ThreadPoolExecutor线程池在美团的最佳实践 回溯 八皇后问题 与 0-1背包 技术学习 线程间通信 计算机网络基础知识总结(各种协议) 大数据Phoenix专题 ClickHouse深度揭秘 hbase 查询组件phoenix redis的设计与实现 第二版 位图 Java并发编程:volatile关键字解析 socket 多路复用原理和代码 select poll epoll mongDB需要注意的事项和 监控命令mongostat mongotop mongoDB的事务
mongoDB学习 mongo的聚合框架、join
Nucky_yang · 2020-06-19 · via 博客园 - Nucky_yang

聚合框架详情 请参考官方文档 

https://docs.mongodb.com/manual/aggregation/

MongoDB 聚合框架(Aggregation Framework)是一个计算框架,它可以:

作用在一个或几个集合上;

  • 对集合中的数据进行的一系列运算;

  • 将这些数据转化为期望的形式;

从效果而言,聚合框架相当于 SQL 查询中的:

  • GROUP BY
  • LEFT OUTER JOIN
  • AS等
整个聚合运算过程称为管道(Pipeline),它是由多个步骤(Stage)组成的
每个管道:
  • 接受一系列文档(原始数据);
  • 每个步骤对这些文档进行一系列运算;
  • 结果文档输出给下一个步骤;

pipeline = [$stage1, $stage2, ...$stageN];
db.<COLLECTION>.aggregate(
    pipeline,
    { options }
);

常见的stage步骤

步骤 作用 SQL等价运算符
$match 过滤 WHERE
$project 投影 AS
$sort 排序 ORDER BY
$group 分组 GROUP BY
$skip/$limit 结果限制 SKIP/LIMIT
$lookup 左外连接 LEFT OUTER JOIN

 常见步骤中的运算符

$match $project $group
$eq/$gt/$gte/$lt/$lte
$and/$or/$not/$in
$geoWithin/$intersect
……
选择需要的或排除不需要的字段
$map/$reduce/$filter
$range
$multiply/$divide/$substract/$add
$year/$month/$dayOfMonth/$hour/$minute/$second
……
$sum/$avg
$push/$addToSet
$first/$last/$max/$min
……

  其他功能

步骤 作用 SQL等价运算符
$unwind 展开数组 N/A
$graphLookup 图搜索 N/A
$facet/$bucket 分面搜索 N/A

比如展开数据就有妙用,可以将内嵌文档展开为多行数据。

使用示例:

  条件过滤步骤 $match

  投影步骤 $project

  展开数据步骤 $unwind

  分组聚合步骤 $group 

 

mongoSQl特有步骤$bucket

$bucket 和select 中的case when 比较像。

$Facet组合$bucket

 

 数据样例

计算到目前为止的所有订单的总销售额
db.orders.aggregate([
      { $group:
          {
            _id: null,
            total: { $sum: "$total" }
          }
      }
])
// 结果: // { "_id" : null, "total" : NumberDecimal("44019609") }
查询2019年第一季度(1月1日~3月31日)已完成订单(completed)的订单总金额和订单总数
db.orders.aggregate([
// 步骤1:匹配条件
      { $match: { status: "completed", orderDate: {
              $gte: ISODate("2019-01-01"),
              $lt: ISODate("2019-04-01") }
             }
      },
// 步骤二:聚合订单总金额、总运费、总数量       { $group: {             _id: null,             total: { $sum: "$total" },             shippingFee: { $sum: "$shippingFee" },             count: { $sum: 1 } }
      },       { $project: {       
// 计算总金额 sum(a+b) as grandTotal         grandTotal: { $add: ["$total", "$shippingFee"] },         count: 1,         _id: 0 }
      } ])
// 结果: // { "count" : 5875, "grandTotal" : NumberDecimal("2636376.00") }

 join操作

适用场景:

一般情况下,设计合理的mongoDB的文档嵌套模型可以避免频繁适用join操作,但是还是有些场景,需要设计主表和关联表做join

1. 内嵌文档数据多,可能上万条或者更多。

2.内嵌文档数据量大,可能数 MB 或者超过 16MB,而且并非常用字段。 
3.内嵌文档或数组元素会频繁修改,一直增长。

mongoDB join的适用限制

MongoDB 对使用引用的集合之间并无主外键检查
MongoDB 使用聚合框架的 $lookup 来模仿关联查询
$lookup 只支持 left outer join
$lookup 的关联目标(from)不能是分片表

example1:

db.contacts.aggregate([
  {
    $lookup:
      {
        from: "groups",
        localField: "group_ids",
        foreignField: "group_id",
        as: "groups"
      }
  }
])
//select a.xx from contacts a left join groups b on a.group_ids=b.group_id
//as 是起的别名

example2:

//表1
db.orders.insert([
   { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
   { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
   { "_id" : 3  }
])
//表2
db.inventory.insert([
   { "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },
   { "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },
   { "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },
   { "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },
   { "_id" : 5, "sku": null, description: "Incomplete" },
   { "_id" : 6 }
])
//join示例
db.orders.aggregate([
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  }
])

返回结果

   "_id" : 1,
   "item" : "almonds",
   "price" : 12,
   "quantity" : 2,
   "inventory_docs" : [
      { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 }
   ]
}
{
   "_id" : 2,
   "item" : "pecans",
   "price" : 20,
   "quantity" : 1,
   "inventory_docs" : [
      { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 }
   ]
}
{
   "_id" : 3,
   "inventory_docs" : [
      { "_id" : 5, "sku" : null, "description" : "Incomplete" },
      { "_id" : 6 }
   ]
}

上面是一对一的关联,还有多对多的关联,详情参考  官方文档:

传送门 https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/