Mongoengine 简明教程
MongoEngine - Aggregation
术语 “ aggregation ” 用于对数据进行处理并返回计算结果的操作。对集合中一个或多个文档字段求和、计数和平均值可称为聚合函数。
MongoEngine 提供了 aggregate() 函数,该函数封装了 PyMongo 的聚合框架。聚合操作使用集合作为输入,并返回一个或多个文档作为结果。
MongoDB 使用数据处理管道这一概念。一个 pipeline 可以有多个阶段。基本阶段提供了提供过滤器和像查询一样运作的内容。其他阶段提供了按一个或多个字段进行分组和/或排序、字符串连接任务、数组聚合工具等的工具。
在 MongoDB 管道创建中定义了以下阶段 -
Name |
Description |
$project |
通过添加新字段或删除现有字段来调整流中每个文档的形状。 |
$match |
对文档流进行筛选,仅允许匹配的文档未经修改进入下一阶段。$match 使用标准 MongoDB 查询。 |
$redact |
通过基于文档中存储的信息限制每条文档的内容,以重新调整每条文档的形状。 |
$limit |
限制文档未经修改地传递给管道 |
$skip |
跳过前 n 个文档,并将剩下的文档未经修改地传递到管道中。 |
$group |
按给定的标识符表达式对输入文档进行分组,并将累加器表达式应用于每个组。输出文档仅包含标识符字段和累加字段。 |
$sort |
按指定的排序键重新排序文档流。 |
$out |
将聚合管道的输出文档写入到集合中。 |
聚合表达式使用字段路径来访问输入文档中的字段。要指定字段路径,请在字段名称前添加一个美元符号 $。表达式可以使用一个或多个布尔运算符($and、$or、$not)和比较运算符($eq、$gt、$lt、$gte、$lte 和 $ne)。
以下算术表达式也用于聚合 −
$add |
相加数字返回总和。接受任意数量的参数表达式 |
$subtract |
返回将第二个值从第一个值中减去的结果 |
$multiply |
相乘数字返回乘积。接受任意数量的参数表达式 |
$divide |
返回将第一个数除以第二个数的结果。接受两个参数表达式 |
$mod |
返回第一个数字除以第二个数字的余数。接受两个参数表达式 |
以下字符串表达式也可用于聚合中 −
$concat |
连接任意数量的字符串 |
$substr |
从指定索引位置开始、最多到指定长度,返回字符串的子字符串 |
$toLower |
将字符串转换为小写。接受一个参数表达式 |
$toUpper |
将字符串转换为大写。接受一个参数表达式 |
$strcasecmp |
执行字符串比较,如果两个字符串相等则返回 0,如果第一个字符串大于第二个字符串则返回 1,如果第一个字符串小于第二个字符串则返回 -1 |
为了演示 aggregate() 函数在 MongoEngine 中的工作方式,我们首先来定义一个名为 orders 的文档类。
from mongoengine import *
con=connect('mydata')
class orders(Document):
custID = StringField()
amount= IntField()
status = StringField()
然后,我们在 orders 集合中添加以下文档 −
_id |
custID |
amount |
status |
ObjectId("5eba52d975fa1e26d4ec01d0") |
A123 |
500 |
A |
ObjectId("5eba536775fa1e26d4ec01d1") |
A123 |
250 |
A |
ObjectId("5eba53b575fa1e26d4ec01d2") |
B212 |
200 |
D |
ObjectId("5eba540e75fa1e26d4ec01d3") |
B212 |
400 |
A |
aggregate() 函数用于查找仅当 status 等于 'A' 时每个 custID 的 amount 字段的和。于是,管道建立如下。
管道中的第一阶段使用 $match 来筛选 status='A' 的文档。第二阶段使用 $group 标识符对 CustID 上的文档进行分组并对 amount 求和。
pipeline = [
{"$match" : {"status" : "A"}},
{"$group": {"_id": "$custID", "total": {"$sum": "$amount"}}}
]
此管道现在用作 aggregate() 函数的参数。
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}