MongoDB聚合管道和CRUD操作入门

在数据库领域,无论是SQL还是NoSQL数据库,聚合操作都是非常重要的一环。MongoDB提供了多种方式来执行聚合操作,包括聚合管道、map-reduce函数和特定聚合方法。本文将重点介绍聚合管道,并使用简单的示例来展示其主要部分。将通过MongoDB shell命令来执行聚合操作。

聚合管道简介

MongoDB的聚合框架基于数据处理管道的概念。聚合管道类似于UNIX世界中的管道。首先,集合中的文档逐个通过管道,然后经过一系列的处理阶段,最终得到结果集。

在聚合管道中,可以出现多个阶段,例如$project、$match、$group、$sort等。这些阶段可以多次出现。

  • $project - 选择、重塑数据
  • $match - 过滤数据
  • $group - 聚合数据
  • $sort - 排序数据
  • $skip - 跳过数据
  • $limit - 限制数据
  • $unwind - 规范化数据

以下是一个使用聚合管道的示例,将使用MongoDB shell命令来执行这个操作。

db.mycollection.aggregate([ {$match: { 'phone_type': 'smart' }}, {$group: { '_id': '$brand_name', total: {$sum: '$price' }}} ])

在这个示例中,首先通过$match阶段过滤文档,然后在下一个阶段对文档进行分组,最终得到结果集。

准备测试数据

为了运行MongoDB shell命令,需要一个数据库和一些测试记录。让创建一个数据库和一个集合。

dept = ['IT', 'Sales', 'HR', 'Admin']; for (i = 0; i < 10; i++) { db.mycollection.insert({ _id: i, emp_code: 'emp_' + i, dept_name: dept[Math.round(Math.random() * 3)], experience: Math.round(Math.random() * 10) }); }

上面的命令将在名为mycollection的集合中插入一些测试文档。

聚合管道的语法

聚合函数接受一个数组作为参数,在数组中可以传递管道的不同阶段。

db.mycollection.aggregate([ {$match: { 'phone_type': 'smart' }}, {$group: { '_id': '$brand_name', total: {$sum: '$price' }}} ])

在这个示例中,传递了两个管道阶段:$match用于过滤记录,$group用于对记录进行分组并生成最终的记录集。

管道阶段详解

在$project阶段,可以添加键、删除键、重塑键。还可以使用一些简单的函数,如$toUpper、$toLower、$add、$multiply等。

db.mycollection.aggregate([ { $project: { _id: 0, department: {$toUpper: '$dept_name'}, new_experience: {$add: ['$experience', 1]} } } ])

在这个聚合查询中,正在投影文档。_id:0意味着隐藏了这个字段,创建了一个新的键名为department,使用之前的dept_name字段的大写形式。需要注意的是,字段‘dept_name’前缀为‘$’符号,以告诉MongoDB shell这个字段是文档的原始字段名。另一个新字段new_experience是通过使用$add函数将1添加到之前的experience字段来创建的。

$match的工作方式与SQL中的‘where子句’类似,用于过滤记录。可能想要匹配的原因是因为想要过滤结果,并且只聚合部分文档或在进行分组后搜索结果集的特定部分。

db.mycollection.aggregate([ { $match: { dept_name: 'Sales' } } ])

顾名思义,$group根据某个键对文档进行分组。假设想要根据部门名称对员工进行分组,并找出每个部门的员工数量。

db.mycollection.aggregate([ { $group: { _id: '$dept_name', no_of_employees: {$sum: 1} } } ])

在这里,_id是分组的键,创建了一个新的键名为no_of_employees,并使用$sum来找出每个组的总记录数。

$sort帮助在聚合后按升序或降序排序数据。假设想要按部门名称的升序排列,并找出员工数量。

db.mycollection.aggregate([ { $group: { _id: '$dept_name', no_of_employees: {$sum: 1} } }, { $sort: { _id: 1 } } ])

对于降序,使用-1。在这里的$sort中,使用了_id字段,因为在聚合的第一个阶段,使用了$dept_name作为_id进行聚合。

$skip和$limit的工作方式与在简单查找时跳过和限制的方式相同。除非首先排序,否则跳过和限制没有意义,否则结果就是未定义的。

db.mycollection.aggregate([ { $group: { _id: '$dept_name', no_of_employees: {$sum: 1} } }, { $sort: { _id: 1 } }, { $skip: 2 }, { $limit: 1 } ])

文档被分组,然后排序,之后跳过两个文档,并将文档限制为一个。

正如知道排序在聚合管道中的工作方式,可以学习$first和$last。它们允许在聚合管道处理文档时,获取每个组的第一个和最后一个值。

db.mycollection.aggregate([ { $group: { _id: '$dept_name', no_of_employees: {$sum: 1}, first_record: { $first: '$emp_code' } } } ])

正如所知,在MongoDB中,文档可以包含数组。在数组中进行分组并不容易。$unwind首先解组数组数据,然后基本上重新组合它,让可以在它上面进行分组计算。

{ a: somedata, b: someotherdata, c: [arr1, arr2, arr3] }

在对‘c’进行$unwind之后,将得到三个文档:

{ a: somedata, b: someotherdata, c: arr1 } { a: somedata, b: someotherdata, c: arr2 } { a: somedata, b: someotherdata, c: arr3 }

让看看一些在SQL和MongoDB中都非常常见的表达式。有它们的替代品。

  • $Sum: 已经看到了它的例子。
  • $avg: 平均值的计算方式与求和类似,但它是计算每个组的平均值。
  • $min: 找出每个分组文档中的最小值。
  • $max: 找出每个分组文档中的最大值。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485