文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

介绍

聚合操作在任何类型的数据库,无论是SQL或者是NoSQL数据库中都非常重要。要执行聚合操作,MognoDB将多个文件的值集中在一起,并且在分组数据上执行各类操作并返回一个单独的结果。SQL使用聚合函数返回一个由多列计算所得的一个值。

MongoDB有三种方式进行聚合计算: 聚合管道,map-reduce函数,单一目的聚合操作方法。

在本文中,我们将专注于聚合管道。我将尽量用简单的示例覆盖每一个主要部分。我们将编写mongo shell命令来执行聚合操作。

第 1 段(可获 1.43 积分)

聚合管道

MongoDB的聚合框架是基于数据处理管道概念。聚合管道类似于UNIX世界中管道符。第一个是集合,将这个集合以一个一个文档的方式发送出去,这些文档经过一些列的处理步骤最后最终形成一个结果集。

在上图中,可以看到集合通过不同的阶段处理,如: $project, $match, $group, $sort ,这些阶段可以重复出现多次。

管道的各个阶段:

第 2 段(可获 1.11 积分)

$project – 选择,重塑数据

$match –过滤数据

$group –聚合数据

$sort – 排序数据

$skip –跳过数据

$limit – 限制数据

$unwind – 规范数据

让我们试着用一个例子来看看聚合,不要担心语法,我会很快就会解释。

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


图中可以看到我们有一个集合, $match 阶段将文档过滤后传递给下一个阶段进行分组,最后得到最终的结果。

第 3 段(可获 0.96 积分)

准备假数据

为了运行mongo shell命令,我们需要一个数据库和一些假记录,让我们开始创建数据库和集合吧。

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

    });

上面的命令会在 mydb 数据库的 mycollection 中插入一些数据。

语法语法

db.mycollection.aggregate([
   {$match:{'phone_type':'smart'}},
   {$group:{'_id':'$brand_name',total:{$sum:'$price'}}}
])
第 4 段(可获 0.5 积分)

语法是相当简单,聚合函数将数组作为参数,在数组中我们可以传递管道的各个阶段。

在上面的例子中,我们已经传递了管道的两个阶段,分别是$match阶段(将过滤掉记录)和$group阶段(将记录集合并产生最终结果集)。

管道的阶段

1. $project

$project阶段我们可以添加一个键值,移除一个键值,重塑一个键值。 有一些简单的函数我们可以用在键值上:$toUpper, $toLower, $add, $multiply等等。

我们用 $project 函数重塑我们创建的文档。

第 5 段(可获 1.23 积分)
db.mycollection.aggregate([
    {
        $project:{
            _id:0,
            'department':{$toUpper:'$dept_name'},
            'new_experience':{$add:['$experience',1]}
        }
    }
])

在这个聚合查询中,我们将解析这个文档,_id:0表示_id是被我们强制隐藏的,不参与聚合查询,在dept_name字段创建一个名为department的新关键字,输出的结果要求为大写。 这里要注意的一点是,字段'dept_name'前面加上'$'符号,告诉mongo shell这个字段是文档的原始字段名。 另一个名为new_experience的新字段通过使用$ add函数将1添加到先前的experience字段中。 我们将得到如下输出:

第 6 段(可获 1.06 积分)

2. $match

它与SQL中的where一样用于过滤记录。使用match的原因是我们想筛选结果,只聚合部分文档或搜索结果集的一部分来作为后续分组的输入。如果只想对部门为销售的数据记录进行聚合,写法如下:

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

3. $group

顾名思义,$group就是按照某些字段进行分组。比如,我们想按照员工的所属部门进行分组,然后统计每一个部门的员工数,写法如下:

第 7 段(可获 1.36 积分)
db.mycollection.aggregate([
    {
        $group:{
            _id:'$dept_name',
            no_of_employees:{$sum:1}
        }
    }
])

这里,_id是分组的关键,我寻找值为no_of_employeesde的department,并使用$ sum来统计每个组中的记录。

让我们改进这个查询以更合理的方式呈现输出。

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

假设我们要将文档分组在多个键上,我们需要做的是在_id字段中指定键的名称。

第 8 段(可获 0.79 积分)
db.mycollection.aggregate([
    {
        $group:{
            _id:{'department':'$dept_name',
                'year_of_experience':'$experience'
            },
            no_of_employees:{$sum:1}
        }
    }
])

4. $sort

排序可帮助您按照需要按升序或降序对数据进行聚合后排序。 假设我们要按升序对部门名称进行分组,并找出员工人数。

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

])
第 9 段(可获 0.46 积分)

降序使用 -1。在$sort中,我使用了_id 字段,这是因为在聚合的第一个阶段中我为 $dept_name取了个别名为 _id 。

5. $skip 和 $limit

当我们做简单的查询时使用$skip and $limit 来跳过和限制结果集。如果我们不首先排序,然后使用skip和limit,那么结果集将是不确定的。

We first skip records and then we limit.

Let’s see an example for the same.

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

])
第 10 段(可获 0.99 积分)

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

6. $first 和$last

就像我们知道在聚合管道中排序是如何工作的,我们可以了解$ first和$ last。 它们允许我们在聚合流水线处理文档时获得每个组中的第一个和最后一个值。

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

7. $unwind

正如我们知道在MongoDB中,文档可以有数组。 对数组中的某个元素进行分组并不容易。 $ unwind首先拆开数组数据,然后基本上以另外一种方式重新聚合起来,让我们对源数组进行分组计算。

第 11 段(可获 1.23 积分)

假设我们有这样的文档:

{
    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
}

8. 聚合表达式

让我们看看在SQL中常用的对应 MongoDB的表达式:

  1. $Sum: 我们已经看到了它的例子.
  2. $avg: 平均,就像和统计计算一样,但它是计算每个组的平均值。
  3. $min: 找到每个分组文档的最小值。
  4. $max: 找到每个分组文档的最大价值。
第 12 段(可获 0.95 积分)

进一步的阅读

以下是一些有用的链接,可以进一步研究和了解MongoDB的聚合。

结语

我没有解释聚合相关的所有主题,但这篇文章将帮助你在项目中开始使用和学习MongoDB的聚合。 附件中有供您参考Mongo shell命令。

第 13 段(可获 0.99 积分)

文章评论