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}