MongoDB 中的聚合

作者 : 慕源网 本文共4739个字,预计阅读时间需要12分钟 发布时间: 2022-01-5 共126人阅读

介绍

欢迎回到 MongoDB 文章系列 – 第 7 部分。在上一篇文章中,我们讨论了 MongoDB 中的高级索引概念。我们还讨论了上限集合、TTL 索引、全文索引等。现在,在本文中,我们将讨论如何在 MongoDB 数据库中实现聚合框架概念。如果您想阅读本系列的前几篇文章,请点击链接。

在上一篇文章中,我们已经讨论了 MongoDB 中的索引。现在,在本文中,我们将讨论 MongoDB 中的聚合框架,此外,我们还将了解如何在数据搜索查询中使用它。因此,数据聚合是一种过程,其中收集所有类型的信息,然后以摘要格式表示。数据聚合的主要目的是进行统计分析、比较分析、计算等分析工作。

MongoDB 中的聚合

聚合框架

在MongoDB中,聚合框架主要用于展示数据的统计和分析分析的结果。该框架始终为我们提供集合内文档的转换。基本上,聚合框架构建了一个管道,通过几个聚合框架块来处理数据,如过滤、投影、分组、排序、限制和跳过。此操作始终处理文档中的数据并返回预测结果。该框架将来自不同的多个文档的所有数据组合在一起,然后对这些分组的数据执行各种操作以返回单个结果。

聚合框架总是返回一个数组作为文档的结果。这使得聚合框架成为一种替代的知识流管道。它实际上充当一个过程流。该框架首先执行文档的转换,然后将文档合并到一个集合中并返回输出。聚合框架中的每个算子都会接收一个文档流,然后对这些文档进行某种转换,然后将转换的结果传递给用户。如果是最后一个管道操作符,则结果直接返回给用户。否则,结果将作为输入传递给下一个转换过程。运算符可以按任何顺序组合并根据需要一次又一次地重复出现。例如,您将执行 “$match”、”$group”、

MongoDB 聚合管道始终由阶段组成。每个阶段都会在文档提交到管道时对其进行转换。管道阶段不会为每个输入文档生成一个输出文档,例如,某些阶段可能会因此生成新文档或过滤文档。管道阶段将在管道内执行多次。MongoDB 在数据集合中提供了 db.collection.aggregate() 方法,因此提供了聚合管道的组合命令。

$Project

投影是聚合管道中附加的强大语法之一。它主要用于聚合管道,而不是将其用作“正常”命令语法。“$project”允许您从子文档中提取字段、重命名字段以及对它们执行引人注目的操作。“$project”将执行的最简单的操作是从传入的文档中单独选择字段以合并或排除字段,使用与命令的第二个参数中使用的语法相同的语法。在下面的示例中,语法将仅返回那些包含集合中字段“author”的文档。

默认情况下,如果“_id”存在于传入的文档中,则它通常会出现(一些管道操作员会移除“_id”,或者它通常在非常旧的投影中被删除)。您可以排除它,如下例所示。包含和排除规则的工作方式通常与“正常”查询相同。您还可以另外重命名投影字段。例如,如果您需要尽可能返回每个用户的“_id”,

 

db.articles.aggregate({ "$project"  : { "author"  : 1,  "_id"  : 0}})  

在上面的语法中,“author”用于表示聚合框架内的字段名值。例如,“$age”将被年龄字段的内容替换(并且很可能是variable,而不是字符串),而“$tags.3”将被替换为tags数组的第四个组件。因此,“$_id”被通过管道返回的每个文档的“_id”字段替换。请注意,我们只需要专门排除“_id”字段,这样它就不会作为结果的一部分返回给用户。例如,我们将能够使用这种语法来制作一个字段的多个副本,以供以后在极其“$group”中使用。

db.users.aggregate({ "$project"  : { "userId"  :  "$_id" ,  "_id"  : 0}})  

最简单的“$project”表达式是单元包含、排除和重命名字段名称(“$fieldname”)。但是,在 $project 语法下还有几个可用的选项,包括不同类型的表达式。有几种可用于聚合的表达式,您可以将它们组合并嵌套到任何深度以创建更复杂的表达式。

  1. 算术表达式 算术表达式允许您操作数值。您通常通过指定要控制的关联数字数组来使用这些表达式。例如,后续表达式将计算“salary”和“bonus”字段的总值。这些是每个表达式的语法。
    • $add (expr1[, expr2, …]) – 接受一个或多个表达式并将它们加在一起
    • $subtract (expr1, expr2) – 接受两个表达式并从第一个表达式中减去第二个。
    • $multiply (expr1[, expr2, …]) – 采用一个或多个表达式并将它们相乘。
    • $divide (expr1, expr2) – 采用两个表达式并将第一个除以第二个。
    • $mod (expr1, expr2) – 采用两个表达式并返回第一个除以第二个的余数。 
  2. 日期表达式

    有时,我们需要对基于时间的单位值执行聚合命令,例如 – 上周发生了什么?还是上个月?还是去年?因此,聚合具有一组表达式,可用于以一些其他有用的方式提取日期信息,例如 “$year”、”$month”、”$week”、”$dayOfMonth”、”$dayOfWeek”、”$dayOfYear “、”$hour”、”$minute” 和 “$second”。所以我们可以只对基本上包含数据类型值的字段使用日期操作。 

  3. 字符串表达式我们需要多次执行一些基本的字符串操作。他们的签名如下,
    • $substr (expr, startOffset, numToReturn)

      这将返回主要参数的子字符串,从第 startOffset 计算机内存单元开始,并与随后的 numToReturn 字节一起(请注意,这通常以字节而不是字符来衡量,因此多字节编码可以注意这一点)。expr 必须对字符串有价值。 

    • $concat (expr1[, expr2, …, exprN])

      连接给定的每个字符串表达式(或字符串)。 

    • $toLower (expr)

      以小写形式返回字符串。expr 必须计算为字符串。 

    • $toUpper (expr)

      以大写形式返回字符串。expr 必须计算为字符串 

$add 的示例

db.employees.aggregate({  
    "$project": {  
        "totalPay": {  
            "$add": ["$salary", "$allowances"]  
        }  
    }  
}) 
$subtract 的示例
db.employees.aggregate({  
    "$project": {  
        "totalPay": {  
            "$subtract": [{  
                "$add": ["$salary", "$bonus"]  
            }, "$401k"]  
        }  
    }  
})  
日期表达式示例
db.employees.aggregate({  
    "$project": {  
        "hiredIn": {  
            "$month": "$joinDate"  
        }  
    }  
})  
$substr 的示例
db.employees.aggregate({  
    "$project": {  
        "email": {  
            "$concat": [{  
                "$substr": ["$firstName", 0, 1]  
            }, ".", "$lastName", "@example.com"]  
        }  
    }  
}) 

$Match

$match 语法基本上过滤了文档,以便我们能够在一组文档上运行关联聚合命令。例如,如果您只需要搜索有关特定州用户的文档,则可以添加“$match”表达式,例如,

{$match : {"state" : "ORL"}}  

“$match”将使用所有常见的问题运算符(“$gt”、“$lt”、“$in”等)。一个值得注意的例外是我们不能在“$match”期间使用地理空间运算符。通常,智能观察是在管道中尽早放置“$match”表达式。这有两个好处,

  1. 它允许您快速分离出不需要的文档,以在管道中提供更快的性能。
  2. 如果它在任何投影或分组之前运行,它将使用索引。

$group

分组是一种处理机制,它基本上使我们有机会根据某些字段对文档进行分组或捆绑,并且还可以组合这些文档的值。数据库级别的一些分组示例是 –

  • 如果我们倾向于每分钟测量一次,并且希望找出每天的常见湿度,我们可能会按“天”字段分组。
  • 如果我们倾向于拥有一组学者,并且希望根据成绩将学生分组,那么我们倾向于根据他们的“成绩”领域进行分组。
  • 如果我们倾向于拥有一组用户,并且希望按城镇检查我们拥有的用户百分比,我们可以按“州”和“城市”字段中的每一个进行聚类,每个城市/州对形成一个聚类。

当我们选择一个字段或字段作为分组依据时,我们需要将它传递给“$group”语法,它作为组的“_id”字段执行。因此,对于高于的例子,我们有,

{"$group" : {"_id" : "$day"}}  
{"$group" : {"_id" : {"state" : "$state", "city" : "$city"}}}

在 MongoDB 中,$group 聚合函数包含一些 group 运算符,它们将实际执行基本的聚合操作。$group 中有两种类型的运算符——一种是算术运算符,另一种是极限运算符。算术运算符包含 $sum 和 $avg 运算符。而极限运算符包含 $max、$min、$first、$last 运算符。

  1. $sum

    此运算符为每个文档添加值并返回结果。此外,虽然上面的示例使用了文字 (1),但这也可以采用更复杂的值并返回结果。

  2. $avg
    返回组内所有输入文档的平均值。
  3. $max返回文档中的最大值。
  4. $min返回文档中的最小值
  5. $first

    返回组中的第一个值。

  6. $last返回组中的最后一个值。

$sum 的示例

db.sales.aggregate({  
    "$group": {  
        "_id": "$country",  
        "totalRevenue": {  
            "$sum": "$revenue"  
        }  
    }  
})  
$avg 的示例
db.sales.aggregate({  
    "$group": {  
        "_id": "$country",  
        "totalRevenue": {  
            "$average": "$revenue"  
        },  
        "numSales": {  
            "$sum": 1  
        }  
    }  
}) 
$last 示例
db.scores.aggregate({  
    "$group": {  
        "_id": "$grade",  
        "lowestScore": {  
            "$min": "$score"  
        },  
        "highestScore": {  
            "$max": "$score"  
        }  
    }  
}) 

$sort

我们可以使用 $sort 语法对文档的特定字段或多个字段执行任何类型的排序操作。如果我们需要对大量文档进行排序,那么始终强烈建议我们首先在管道开始时按所需顺序对数据进行排序,并对其应用索引。否则,将花费更多的时间,这样,过程响应就会变慢或延迟。$sort 是另一个类似于 $group 的路障操作示例。由于在这个过程中需要对所有记录进行相应的排列,以便对指定进程中的记录进行排序,那么它需要对所有记录进行排序,然后才将单个分片发送到mongo结果中进行进一步处理。

db.employees.aggregate({  
    "$project": {  
        "compensation": {  
            "$add": ["$salary", "$bonus"]  
        },  
        "name": 1  
    }  
}, {  
    "$sort": {  
        "compensation": -1,  
        "name": 1  
    }  
}) 

结论

在本文中,我们讨论了一些聚合框架语法,如 $match、$group、$sort、$project 等。这些语法基本上用于执行多种类型的数学或分析操作。在下一篇文章中,我们将讨论 MongoDB 中聚合框架的更多语法。我希望这篇文章能帮到你。欢迎任何与本文相关的反馈或查询。


慕源网 » MongoDB 中的聚合

常见问题FAQ

程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!

发表评论

开通VIP 享更多特权,建议使用QQ登录