MongoEngine – 聚合
术语’ 聚合 ‘用于处理数据并返回计算结果的操作。在一个集合中的一个或多个文件字段上寻找总和、计数和平均数可以被称为聚合函数。
MongoEngine提供了 aggregation() 函数,封装了PyMongo的聚合框架。聚合操作使用一个集合作为输入并返回一个或多个文档作为结果。
MongoDB使用数据处理管道的概念。一个 流水线 可以有多个阶段。基本阶段提供的是提供过滤器和像查询一样的操作。其他阶段提供按一个或多个字段进行分组和/或排序的工具、字符串连接任务、数组聚合工具等。
以下是在MongoDB管道创建中定义的阶段
| 名称 | 描述 | 
|---|---|
| $project | 通过添加新字段或删除现有字段,重塑流中的每个文档。 | 
| $match | 过滤文档流,只允许匹配的文档不加修改地进入下一阶段。$match使用标准的MongoDB查询。 | 
| $redact | 根据存储在文档本身的信息,通过限制每个文档的内容来重塑每个文档。 | 
| $limit | 限制未经修改的文档进入流水线。 | 
| $skip | 跳过前n个文档,将剩余的文档未经修改地传递给流水线。 | 
| $group | 通过给定的标识符表达式对输入文档进行分组,并将累加器表达式应用于每个组。输出的文档只包含标识符字段和累积字段。 | 
| $sort | 按指定的排序键对文档流进行重新排序。 | 
| $out | 将聚合管道的结果文档写到一个集合中。 | 
| $add | 将数字相加,返回总和。接受任何数量的参数表达式 | 
|---|---|
| $subtract | 返回第二个数值与第一个数值相减的结果。 | 
| $multiply | 将数字相乘,返回乘积。接受任意数量的参数表达式 | 
| $divide | 返回第一个数字除以第二个数字的结果。接受两个参数表达式 | 
| $mod | 返回第一个数字除以第二个数字的余数。接受两个参数表达式 | 
以下字符串表达式也可用于聚合 −
| $concat | 将任何数量的字符串连接起来 | 
|---|---|
| $substr | 返回一个字符串的子串,从指定的索引位置开始,到指定的长度。 | 
| $toLower | 将一个字符串转换为小写字母。接受单一参数表达式 | 
| $toUpper | 将一个字符串转换为大写字母。接受一个单一的参数表达式 | 
| $strcasecmp | 执行字符串比较,如果两个字符串相等,则返回0,如果第一个字符串大于第二个字符串,则返回1,如果第一个字符串小于第二个字符串,则返回1。 | 
为了演示 aggregate() 函数在MongoEngine中是如何工作的,让我们首先定义一个名为orders的Document类。
from mongoengine import *
con=connect('mydata')
class orders(Document):
   custID = StringField()
   amount= IntField()
   status = StringField()
然后我们在订单集合中添加以下文件 –
| _id | custID | 数量 | 状态 | 
|---|---|---|---|
| ObjectId(“5eba52d975fa1e26d4ec01d0”) | A123 | 500 | A | 
| ObjectId(“5eba536775fa1e26d4ec01d1”) | A123 | 250 | A | 
| ObjectId(“5eba53b575fa1e26d4ec01d2”) | B212 | 200 | D | 
| ObjectId(“5eba540e75fa1e26d4ec01d3”) | B212 | 400 | A | 
aggregate()函数仅在状态等于’A’时用于查找每个custID的金额字段的总和。因此,流水线的构造如下。
管道的第一阶段使用match来过滤状态=’A’的文件。第二阶段使用group标识符对CustID的文档进行分组,并执行金额之和。
 pipeline = [
{"match" : {"status" : "A"}},
{"group": {"_id": "custID", "total": {"sum": "$amount"}}}
]
这个管道现在被用作聚合()函数的参数。
docs = orders.objects().aggregate(pipeline)
我们可以用一个for循环来迭代文档光标。下面给出了完整的代码–
from mongoengine import *
con=connect('mydata')
class orders(Document):
   custID = StringField()
   amount= IntField()
   status = StringField()
pipeline = [
   {"match" : {"status" : "A"}},
   {"group": {"_id": "custID", "total": {"sum": "$amount"}}}
   ]
docs = orders.objects().aggregate(pipeline)
for doc in docs:
   print (x)
对于给定的数据,将产生以下输出 −
{'_id': 'B212', 'total': 400}
{'_id': 'A123', 'total': 750}
极客教程