如何使用 MongoDB 的聚合管道?

举报
Xxy_1008 发表于 2024/10/30 09:58:31 2024/10/30
【摘要】 聚合管道的概念聚合管道是 MongoDB 中用于处理数据和生成统计结果的强大工具。它允许将多个数据处理阶段(stage)组合在一起,每个阶段对输入数据进行特定的操作,然后将结果传递给下一个阶段。可以把它想象成一个数据处理的流水线,数据在这个流水线上依次经过不同的 “加工站”,最终输出经过复杂处理后的结果。例如,从原始的订单数据中,先筛选出特定时间段的订单,然后对这些订单进行分组,计算每个分组...
  1. 聚合管道的概念
    • 聚合管道是 MongoDB 中用于处理数据和生成统计结果的强大工具。它允许将多个数据处理阶段(stage)组合在一起,每个阶段对输入数据进行特定的操作,然后将结果传递给下一个阶段。可以把它想象成一个数据处理的流水线,数据在这个流水线上依次经过不同的 “加工站”,最终输出经过复杂处理后的结果。例如,从原始的订单数据中,先筛选出特定时间段的订单,然后对这些订单进行分组,计算每个分组的总金额,最后按照总金额进行排序。
  2. 聚合管道的基本操作阶段
    • $match 阶段(筛选)
      • 这是聚合管道的起始阶段,用于筛选符合特定条件的文档。它类似于查询操作中的find方法,但在聚合管道中有更广泛的用途。例如,要从一个名为 “orders” 的集合中筛选出状态为 “已完成” 的订单,可以使用以下聚合管道:
       db.orders.aggregate([
         {
           $match: {
             status: "已完成"
           }
         }
       ]);


  • 这里$match操作符接受一个查询条件对象,只有满足这个条件的文档才会被传递到下一个聚合阶段。
  • $group 阶段(分组)
    • 用于将文档按照指定的字段进行分组,并可以在分组的基础上进行计算。例如,对 “orders” 集合中的订单按照 “customer_id” 进行分组,并计算每个客户的订单总金额。假设订单文档中有 “customer_id” 和 “amount” 字段,聚合管道如下:
       db.orders.aggregate([
         {
           $match: {
             status: "已完成"
           }
         },
         {
           $group: {
             _id: "$customer_id",
             total_amount: {
               $sum: "$amount"
             }
           }
         }
       ]);


  • 这里$group操作符中的_id字段指定了分组的依据(这里是 “customer_id”),total_amount是一个新的计算字段,通过$sum操作符对每个分组内的 “amount” 字段进行求和。
  • $sort 阶段(排序)
    • 用于对聚合管道的结果进行排序。例如,按照上一步计算出的 “total_amount” 字段对结果进行降序排序:


       db.orders.aggregate([
         {
           $match: {
             status: "已完成"
           }
         },
         {
           $group: {
             _id: "$customer_id",
             total_amount: {
               $sum: "$amount"
             }
           }
         },
         {
           $sort: {
             total_amount: -1
           }
         }
       ]);


  • 这里$sort操作符接受一个排序条件对象,键是要排序的字段,值可以是1(升序)或-1(降序)。


  1. 其他常用阶段
    • $project 阶段(投影)
      • 用于选择要在最终结果中包含或排除的字段。例如,在前面的聚合管道基础上,只保留 “customer_id” 和 “total_amount” 字段,并且将 “customer_id” 字段重命名为 “id”:


       db.orders.aggregate([
         {
           $match: {
             status: "已完成"
           }
         },
         {
           $group: {
             _id: "$customer_id",
             total_amount: {
               $sum: "$amount"
             }
           }
         },
         {
           $sort: {
             total_amount: -1
           }
         },
         {
           $project: {
             id: "$_id",
             total_amount: 1,
             _id: 0
           }
         }
       ]);


  • 这里$project操作符中的1表示包含该字段,0表示排除该字段。通过将_id设置为0,排除了默认的分组标识字段,同时将 “customer_id”($_id)重命名为 “id”。
  • $limit 阶段(限制数量)
    • 用于限制聚合管道最终输出的结果数量。例如,只获取前 10 个客户的订单总金额信息:
       db.orders.aggregate([
         {
           $match: {
             status: "已完成"
           }
         },
         {
           $group: {
             _id: "$customer_id",
             total_amount: {
               $sum: "$amount"
             }
           }
         },
         {
           $sort: {
             total_amount: -1
           }
         },
         {
           $project: {
             id: "$_id",
             total_amount: 1,
             _id: 0
           }
         },
         {
           $limit: 10
         }
       ]);


  1. 复杂聚合操作示例
    • 假设我们有一个 “students” 集合,其中包含学生的成绩信息,文档结构包括 “student_id”、“course”、“grade” 等字段。我们想要计算每个学生的平均成绩,并找出平均成绩最高的 10 名学生。聚合管道如下:


     db.students.aggregate([
       {
         $group: {
           _id: "$student_id",
           average_grade: {
             $avg: "$grade"
           }
         }
       },
       {
         $sort: {
           average_grade: -1
         }
       },
       {
         $limit: 10
       },
       {
         $project: {
           student_id: "$_id",
           average_grade: 1,
           _id: 0
         }
       }
     ]);


  • 这个聚合管道首先通过$group阶段按照 “student_id” 对学生进行分组,并使用$avg操作符计算每个学生的平均成绩。然后通过$sort阶段按照平均成绩进行降序排序,接着通过$limit阶段获取前 10 名学生的信息,最后通过$project阶段调整输出结果的字段。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。