python mongodb aggregate

使用聚合框架可以对集合中的文档进行变换和组合,基本上可以使用多个构建创建一个管道(pipeline),用于对一连串的文档进行处理。这些构建包括筛选(filtering),投射(projecting),分组(grouping),排序(sorting),限制(limiting)和跳过(skipping)
假如有下面这个文档集合,
(1)想提取每隔文档中的name,
(2)并按照名字进行分组,统计名字出现的次数,
(3)并按照age进行排序,限制返回前10个
(1)这里第一个提取name需要用到投射

{"$project":{"name":1}}

这样就把name提取出来
(2)分组,统计总和

{"$group":{"_id":"$name","count":{"$sum":1}}}

(3)排序以及limit

{"$sort":{"age":1}}{"$limit":10}

将这些构件传递给aggregate函数
demo

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.cap
ss.drop()
ss=db.cap
ss.insert_one({"name":"1","age":2})
ss.insert_one({"name":"2","age":2})
ss.insert_many([{"name":"4","age":6},
                {"name":"4","age":6}])
for i in ss.aggregate([{"$project":{"name":1}},{"$group":{"_id":"$name","count":{"$sum":1}}},{"$sort":{"age":1}},{"$limit":10}]):
    print(i)

管道操作符

1 $match

m a t c h 是 对 文 档 进 行 筛 选 , 通 常 放 在 管 道 的 第 一 位 , 先 筛 选 再 聚 合 , match是对文档进行筛选,通常放在管道的第一位,先筛选再聚合, matchmatch可以和$gt $in等一起使用

{"$match":{"name":{"$in":["1","2"]}}}

2 $project

投射功能强大,使用投射可以从文档中提取字段,重命名字段,还可以在这些字段上做一些有趣的操作
最简单的一个操作是从文档中选择想要或者不想要的字段

ss.aggregate({"$project":{"name":1,"_id":0}})

重命名字段
将name字段重命名为testRename

{"$project":{"testRename":"$name","_id":0}}

数学表达式
$add【param1,param2】 相加
$subtract 【param1,param2】相减
$multiply 【param1,param2,param3…】相乘
$divide 返【param1,param2】回第一个表达式与第二个表达式的商
$mod【param1,param2】 取余

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.math
ss.drop()
ss=db.math
ss.insert_one({"chinese":1,"english":2})
ss.insert_one({"chinese":1,"english":2})
ss.insert_many([{"chinese":1,"english":2},
                {"chinese":1,"english":2}])
for i in ss.aggregate([{"$project":{"total":{"$add":["$chinese","$english"]}}}]):
    print(i)

日期表达式,只能用来操作日期字段
$year
$month
$week
$dayOfMonth
$dayOfYear
$dayOfWeek
$hour
$minute
$second

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.math
ss.drop()
ss=db.math
ss.insert_one({"chinese":1,"english":2,"time":datetime.now()})
ss.insert_one({"chinese":1,"english":2,"time":datetime.now()})
ss.insert_many([{"chinese":1,"english":2,"time":datetime.now()},
                {"chinese":1,"english":2,"time":datetime.now()}])
for i in ss.aggregate([{"$project":{"time":{"$year":"$time"}}}]):
    print(i)

字符串表达式
$substr【param1,start,numReturn】
其中param1必须是字符串,从start字节开始,返回numReturn字节
$concat 【returnName:[param1,param2…]】字符串拼接
$toLower 小写
$toUpper 大写

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.math
ss.drop()
ss=db.math
ss.insert_one({"chi":"你好吗","eng":"Hello"})

for i in ss.aggregate([{"$project":{"ss":{"$concat":["$chi","$eng"]}}}]):
    print(i)

for i in ss.aggregate([{"$project":{"s":{"s1":{"$toLower":"$eng"},"s2":{"$toUpper":"$eng"}}}}]):
    print(i)
for i in ss.aggregate([{"$project":{"s1":{"$toLower":"$eng"}}}]):
    print(i)

for i in ss.aggregate([{"$project":{"ss":{"$substr":["$eng",2,2]}}}]):
    print(i)

逻辑表达式
$cmp:[param1,param2]
比较两个数,param1等于param2返回0,param1param2返回正数
$strcasecmp:[string1,string2]
比较string1和string2 ,区分大小写
e q / eq/ eq/ne/ g t / gt/ gt/gte/ l t / lt/ lt/lte:[param1,param2]
返回比较结果(true,false)
$and
$or
$not
$cond:[boolearnParam1,trueExpr,falseExpr]
如果boolearnParam1为true,返回trueExpr,否则返回falseExpr
$ifNull:[param1,replacementExpr]
如果param1是null,返回replacementExpr,否则返回param1
通过这些操作符,就可以在聚合中使用更复杂的逻辑
demo
为学生打分,出勤占10%,日常占30%,期末占60%,假如是老师喜欢的学生,那么是100分

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.luoji
ss.drop()
ss=db.luoji
ss.insert_one({"attend":90,"qimo":89,"richang":88,"teacherLove":True})
ss.insert_one({"attend":92,"qimo":89,"richang":88,"teacherLove":True})
ss.insert_one({"attend":90,"qimo":89,"richang":88,"teacherLove":False})
ss.insert_one({"attend":99,"qimo":99,"richang":99,"teacherLove":False})
for i in ss.aggregate([{"$project":{"grade":{
                        "$cond":["$teacherLove",
                                 100,
                                 {
                                     "$add":[
                                         {"$multiply":[.1,"$attend"]},
                                         {"$multiply":[.3,"$richang"]},
                                         {"$multiply":[.6,"$qimo"]},
                                     ]
                                 }]
                        }}}]):
    print(i)

3 $group

g r o u p 操 作 可 以 将 文 档 依 据 特 定 字 段 的 不 同 值 进 行 分 组 。 如 果 选 定 了 需 要 进 行 分 组 的 字 段 , 就 可 以 将 选 定 的 字 段 传 递 给 “ group操作可以将文档依据特定字段的不同值进行分组。 如果选定了需要进行分组的字段,就可以将选定的字段传递给“ groupgroup”函数的"_id"字段。例如
python mongodb aggregate_第1张图片
算数操作符
KaTeX parse error: Expected '}', got 'EOF' at end of input: …b.aggregate([{"group":{"_id":“KaTeX parse error: Expected '}', got 'EOF' at end of input: …try","total":{"sum”:"$value"}}}])
$avg:value
返回每个数组的平均值

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.country
ss.drop()
ss=db.country
ss.insert_one({"country":"china","value":89})
ss.insert_one({"country":"china","value":99})
ss.insert_one({"country":"china","value":79})
ss.insert_one({"country":"japan","value":69})
ss.insert_one({"country":"japan","value":59})
ss.insert_one({"country":"japan","value":49})


for i in ss.aggregate([{"$group":
                            {"_id":"$country",
                             "total":{"$sum":"$value"},
                             "avg":{"$avg":"$value"}}}]):
    print(i)

极值操作符
下面的四个操作符可用于得到数据集合中的边缘值
$max:expr
返回分组中的最大值
$min:expr
返回分组中的最小值
$first:expr
返回分组中的第一个值,忽略后面的所有值。只有排序后,明确知道数据顺序时这个操作才有意义。
l a s t : e x p r 与 last:expr 与 last:exprfirst相反,返回分组的最后一个值
max min demo

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.score
ss.drop()
ss=db.score
ss.insert_one({"name":"cx","class":"math","value":89})
ss.insert_one({"name":"xy","class":"math","value":99})
ss.insert_one({"name":"cx","class":"chinese","value":59})
ss.insert_one({"name":"xy","class":"chinese","value":69})
ss.insert_one({"name":"cx","class":"english","value":99})
ss.insert_one({"name":"xy","class":"english","value":39})



for i in ss.aggregate([{"$group":
                            {"_id":"$class",
                             "max":{"$max":"$value"},
                             "min":{"$min":"$value"}}}]):
    print(i)

数组操作符
$addToSet:expr
去过当前数组不包含expr,则将expr添加到数组中。
$push:expr
直接将expr添加到数组中

**

$unwind

**
拆分可以将数组中的每一个值拆分成单独的文档。例如有一篇拥有多条评论的博客文章,可以使用$unwind将每条评论拆分成一个独立的文档:

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.blog
ss.drop()
ss=db.blog
ss.insert_one({"auther":"cx","title":"mongodb","comments":[
            {"auther":"小明",
             "text":"牛逼",
             "time":datetime.now()},
            {"auther":"小红",
             "text":"很牛逼",
             "time":datetime.now()}
]})

for s in ss.find():
    print(s)

for i in ss.aggregate([{"$unwind":"$comments"}]):
    print(i)

如果想在查询中得到特殊的子文档,这个操作就很重要了,先试用 u n w i n d 将 数 组 拆 分 , 然 后 使 用 unwind将数组拆分,然后使用 unwind使match进行选择。例如

from pymongo import MongoClient
from datetime import datetime
conn=MongoClient('localhost',27017)
db=conn.Fin
# db.create_collection('captest', capped=True, size=20000000000,max=3)

ss=db.blog
ss.drop()
ss=db.blog
ss.insert_one({"auther":"cx","title":"mongodb","comments":[
            {"auther":"小明",
             "text":"牛逼",
             "time":datetime.now()},
            {"auther":"小红",
             "text":"很牛逼",
             "time":datetime.now()}
]})
for i in ss.aggregate([{"$unwind":"$comments"},{"$match":{"comments.auther":"小红"}}]):
    print(i)

**

$sort

**
排序
**

$limit

**
返回n个文档
**

$skip

**
跳过n个文档
**

聚合命令

**
count
count是最简单的聚合工具,用于返回集合中的文档数量

print(ss.estimated_document_count())

distinct
用来找出给定键的所有不同值。使用时必须指定集合和键
python mongodb aggregate_第2张图片

你可能感兴趣的:(Python)