zoukankan      html  css  js  c++  java
  • MongoDB 高级查询_aggregate聚合管道

    MongoDB 聚合管道(AggregationPipeline)

    使用聚合管道可以对集合中的文档进行变换和组合。实际项目应用主要是表关联查询、数据的统计。

    MongoDB 中使用 db.COLLECTION_NAME.aggregate([{<stage>},...]) 方法 来构建和使用聚合管道。下面是官网给的实例,感受一下聚合管道的用法。

    第一个步时查找orders集合中status为A的数据,第二步是根据cust_id做了一个分组,第三步是将属于同一个分组中的amount进行求和后给total字段赋值

    MongoDB Aggregation 管道常用的操作符与表达式

    MongoDB Aggregation 管道常用的操作符

    $project :增加、删除、重命名字段

    $match:条件匹配。只满足条件的文档才能进入下 一阶段

    $limit 限制结果的数量

    $skip 跳过文档的数量

    $sort 条件排序。

    $group 条件组合结果 统计

    $lookup 操作符 用以引入其它集合的数 据 (表关联查询)

    SQL 和 NOSQL 对比:

    MongoDB Aggregation 管道常用的表达式

    管道操作符作为“键”,所对应的“值”叫做管道表达式。例如{$match:{status:"A"}},$match 称为管道操作符,而 status:"A"称为管道表达式, 是管道操作符的操作数(Operand)。

    每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的。

    数据模拟

    在演示每个操作符的使用之前,先要有数据,这里我们先创建一个数据库()和一个order集合,order_item集合来进行演示操作

    先使用数据库aggregation(使用及创建)

    use aggregation

    然后直接插入数据的方式来创建集合

    db.order.insert({"order_id":"1","uid":10,"trade_no":"111","all_price":100,"all_num":2}) 
    db.order.insert({"order_id":"2","uid":7,"trade_no":"222","all_price":90,"all_num":2}) 
    db.order.insert({"order_id":"3","uid":9,"trade_no":"333","all_price":20,"all_num":6})
    
    
    db.order_item.insert({"order_id":"1","title":"商品鼠标 1","price":50,num:1}) 
    db.order_item.insert({"order_id":"1","title":"商品键盘 2","price":50,num:1}) 
    db.order_item.insert({"order_id":"1","title":"商品键盘 3","price":0,num:1})
    db.order_item.insert({"order_id":"2","title":"牛奶","price":50,num:1}) 
    db.order_item.insert({"order_id":"2","title":"酸奶","price":40,num:1})
    db.order_item.insert({"order_id":"3","title":"矿泉水","price":2,num:5}) 
    db.order_item.insert({"order_id":"3","title":"毛巾","price":10,num:1})

    $project

    修改文档的结构,可以用来重命名、增加或删除文档中的字段。比如:要求查找 order 只返回文档中 trade_no 和 all_price 字段

    db.order.aggregate([ {
      $project: {
        trade_no:1,
        all_price:1
      }
    } ])

    $match

    作用:用于过滤文档。用法类似于 find() 方法中的参数。比如下面找出all_price字段的值大于等于90的数据

    db.order.aggregate([
      {
        $project:{ order_id:1,trade_no:1, all_price:1 }
      },
      {
        $match:{"all_price":{$gte:90}}
      }
    ])

    $group

    将集合中的文档进行分组,可用于统计结果。比如:统计每个订单的订单数量,按照订单号分组

    db.order_item.aggregate(
      [
        {
          $group: {_id: "$order_id", total: {$sum: "$num"}}
        }
      ]
    )

    查询结果显示order_id为3的总数total有6个.......

    $sort

    将集合中的文档进行排序

    db.order.aggregate([
      {
        $project:{ trade_no:1, all_price:1 }
      },
      {
        $match:{"all_price":{$gte:90}}
      },
      {
        $sort:{"all_price":1}
      }
    ])

    $limit 限制结果的数量

    这个操作符在实际项目中可以用于分页操作中查找多少条数据可以结合$skip来完成分页功能

    db.order.aggregate([
      {
        $project:{ trade_no:1, all_price:1 }
      },
      {
        $match:{"all_price":{$gte:90}}
      },
      {
        $sort:{"all_price":-1}
      },
      {
        $limit:1
      }
    ])

    $skip 跳过文档的数量

    db.order.aggregate([
      {
        $project:{ trade_no:1, all_price:1 }
      },
      {
        $match:{"all_price":{$gte:90}}
      },
      {
        $sort:{"all_price":-1}
      },
      {
        $skip:1
      }
    ])

    $lookup 表关联

    比如我想查找order集合和order_item集合,然后得出下面这样的结果

    [{
      Order_id:'1',
      Trade_no:'',
      Items:[{
        Title:'鼠标',
        Price: 20
      }, {
        Title: '键盘',
        Price: 20
      }]
    }, {
      Order_id: '2',
      Trade_no: '',
      Items: [{
        Title: '鼠标',
        Price: 20
      }, {
        Title: '键盘',
        Price: 20
      }]
    }]

    那么我们可以使用$lookup关联查询

    db.order.aggregate([
      {
        $lookup:
          {
            from: "order_item",
            localField: "order_id",
            foreignField: "order_id",
            as: "items"
          }
      }
    ])

    跟其他操作符来一起使用,比如$match,找出all_price字段大于等于90的数据

    db.order.aggregate([
      {
        $lookup:
          {
            from: "order_item",
            localField: "order_id",
            foreignField: "order_id",
            as: "items"
          }
      },
      {
        $match:{"all_price":{$gte:90}}
      }
    ])

  • 相关阅读:
    使用 jsPlumb 绘制拓扑图 —— 异步加载与绘制的实现
    改善记忆力的二十种记忆方法,随便你挑!
    怎样完成一次比较漂亮的晋升面试演讲
    产品运维的思考与总结
    Jtester+unitils+testng:DAO单元测试文件模板自动生成
    生活、工作和理想
    推荐《需求:缔造伟大商业传奇的根本力量》
    星光之旅
    谈读书
    生命之反思
  • 原文地址:https://www.cnblogs.com/LO-ME/p/10873005.html
Copyright © 2011-2022 走看看