pipeline 对mongodb的collection进行运算,筛选,截取,排序操作。
一、pipeline 格式
pipeline = [
{$project:?},
{$match:?},
{$group:?},
{$sort :?},
{$limit:?},
{$skip :?},
{$unwind:?},
{$redact:?},
{$sample:?},
{$out:?},
]
##常用
pipeline = [
{$project:?},
{$match:?},
{$group:?},
{$sort :?},
{$limit:?},
]
说明:
1、$project
重命名及增加,删除字段
db.collection.aggregate({'$project': {
key1:1, // 保留key1字段
key2:0, //不要key2字段(常用以去掉'_id',因为'_id'会默认被包含)
keyalias:'$key3' //将key3字段重命名为keyalias
}}
2、$match
过滤筛选操作
$match
语法和 db.collection.find()
语法相同
3、$limit
返回数据条数
db.collection.aggregate({$limit:5})
只返回最多5条数据
4、$skip
从数据集合开始跳过n条数据
语法和$limit
一样,n为正整数
5、$unwind
将数组元素拆分成独立字段
语法:{"$unwind":'字段名'}
,该字段的值必需是数组
例子:假设collection 原版的数据是:
{_id:xxxxxxx,
key1: [
{subk1: value,
subk2: value
},
{subk3: value,
subk2: value
}],
key2: value,
key3: value
}
通过 db.collection.aggregate({$unwind:'$key1'}) 后:
{result:[
{
_id: xxxxxxx,
key1: {subk1: value, subk2: value},
key2: value,
key3:value
},
{
_id: xxxxxxx
key1: {subk3: value, subk2: value},
key3: value
}
]
}
6、$group
根据指定字段值进行分组,可以包含算数类型的表达式操作符
例子:假设collection数据为
[{
_id: xxxxxxx,
key1: v1,
key2: 2,
},
{
_id: xxxxxxxx,
key1: v2,
key2: 5
},
{
_id: xxxxxxx,
key1: v1,
key2: 7
},
]
通过 db.collection.aggregate({$group:{_id:'$key1', key2sum:{$sum :'$key2'}}}) 后:
{result:[
{key1: v1, key2sum: 9},
{key1: v2, key2sum: 5}
]}
7、$sort
对结果进行排序,语法和 db.collection.find().sort()
语法一致
{$sort:{key1: -1, key2:1}}: key1值降序,key2值升序
更多请参考官网
二、常用操作示例
1、取某一段范围
pipeline = [
{$match:{ts:{$gte: 100000, $lt:120000}}}
]
> db.colliction.aggregate(pipeline)
筛选出ts在[100000, 120000] 之间的数据
2、去掉值为null的数据
pipeline = [
{$match:{key1:{"$ne":null}}}
]
> db.colliction.aggregate(pipeline)
去掉key1为null的数据
3、多个操作组合示例
pipeline = [
{'$project':{'minu': 1, '_id': 0, 't': 1, 'r': 1}},
{'$unwind': '$minu'},
{'$match': {'minu': {'$ne': None}}},
{'$project': {'r': 1, 'trans_count': '$minu.k', 'ts': {'$add': ['$t', '$minu.t']}}},
{'$match': {'ts': {'$gte': 1457059140, '$lt': 1457060040}}},
{'$project': {'trans_count': 1, 'id': 0, 'r': 1}},
{'$group': {'trans_count': {'$sum': '$trans_count'}, 'id': '$r'}},
{'$project': {'trans_count': 1, 'id': 0, 'ret_code': '$id'}},
{'$sort': {'trans_count': -1, 'ret_code': 1}}
]
> db.colliction.aggregate(pipeline)
mongodb会顺序执行以下内容:
①获取minu, t, r 字段的内容, 去掉_id字段
②分解minu的数据
③去掉minu字段为null的数据
④将保留r字段, minu.k重命名为trans_count, ts为t和minu.t的和
⑤获取ts在[1457059140, 1457060040]之间的数据
⑥获取trans_count, r 字段
⑦按照r字段的值分组,同一个r值得trans_count相加(id的值是r字段的内容)
⑧保留trans_count字段,_id重命名为ret_code
⑨根据trans_count降序,ret_code升序排列
4、其他示例
##获取发布时间为2020.03.21,且次数为3次
##对 price 字段进行分组并统计次数
pipeline = [
{"$match":{"$and":[{"pub_time":"2020.03.21"},{"time":3}]}},
{"$group":{"_id":$price,"counts":{"$sum":1}}},
{"$sort":{"counts":-1}},
{"$limit":3},
]
##获取发布时间为2020.03.21,且区域包含上海
#根据 cates 字段进行分组然后分隔,并统计次数
pipeline = [
{"$match":{"$and":[{"pub_time":"2020.03.21"},{"area":{"$all":['上海']}}]}},
{"$group":{"_id":{"$slice":["$cates",2,1]},"counts":{"$sum":1}}},
{"$limit":3},
]
##获取发布时间为2020.03.21,且区域包含上海,且look字段不包含 '-'
#根据 look 字段进行分组,且 求每组 price 字段的平均值
pipeline = [
{"$match":{"$and":[{"pub_time":"2020.03.21"},{"area":{"$all":['上海']}},{'look':{'$nin':['-']}}]}},
{"$group":{"_id":"$look","avg_price":{"$avg":$price}}},
{"$sort":{'avg_price':-1}},
]
##直接分组
db.colliction.group({
"key": {'storeName': 1}, //storeName 存在
cond: {"$and":[{ "createTime": { $gte: ISODate("2020-02-10T00:00:00Z") } },{ "createTime": { $lte: ISODate("2020-02-20T23:59:59Z") } }]}, //取出指定时间段
reduce: function(obj,storeName) {storeName.count++}, //对storeName 做自增运算
initial: { count:0} //初始值为0
})