许久没有再写博客,发生了很多事。最近在学习MongoDB,简单记录一下mongoDB的聚合语句:
db.alarm.aggregate(
[
// {$match:{'$and': [{'event_status': {'$in': ['white', 'rejected']}}]}},
// {$unwind: "$tag"}, //这里要特别注意不能够使用unwind
{'$project': {'emergency_degree': 1, 'tag3': 1, 'business_id': 1, 'tag': 1, 'service_status': 1, 'event_status': 1, 'asset_type': 1, 'company_id': 1, 'source': 1, 'create_time': 1, 'latest_time': 1, 'asset': 1,
'_id': {'$concat': ['$company_id', '-', '$asset']}}},
// {'$match': {'$and': []}},
{'$group':
{'emergency_degree': {'$max': '$emergency_degree'},
'tags': {'$addToSet': '$tag'},
'create_time': {'$min': '$create_time'},
'certainty_levels': {'$addToSet': '$tag3'},
'business_id': {'$min': '$business_id'},
'company_id': {'$first': '$company_id'},
// 'alarm_ids': {'$addToSet': {'$cond': {'then': '$_id', 'else': '', 'if': {'$or': [{'$eq': ['$_id', 'inited']}, {'$eq': ['$_id', 'rejected']}]}}}},
'alarm_ids':{'$addToSet':{'$cond':{
'if':{ "$or": [{ "$eq": ["$event_status",'inited' ]}, { "$eq": ["$event_status", 'rejected']}]},
'then':'$_id',
'else':''
}}},
'alarm_num': {'$sum': {'$cond': {'then': 1, 'else': 0, 'if': {'$eq': ['$event_status', 'inited']}}}},
'latest_time': {'$max': '$latest_time'},
'asset': {'$first': '$asset'},
'event_status': {'$addToSet': '$event_status'},
'service_status': {'$max': '$service_status'},
'_id': '$_id',
'tag3': {'$max': '$tag3'},
'asset_type': {'$min': '$asset_type'},
'source': {'$first': '$source'}}},
{'$match': {'tag3': 2}},
{'$sort': {'latest_time': -1}}],
{'$skip':100},
{'$limit':100},
{
allowDiskUse:true
})
一些点与小坑记录如下
1、$unwind,在MongoDB中实现了类似于Python中flatten列表的功能,但是unwind之后会影响整个aggregate语句的count计数,原因暂时不清楚。
2、$cond,条件语句,本来想写一个满足条件就addToset,不满足条就continue。但是$cond这一个聚合操作符中似乎没有continue,于是将不满足的直接提取成空串。由于这个聚合语句是送到pymongo进行执行,后续可以利用Python本身的filter语句来进行后续处理。同时需要注意的是,这里的$cond被写成了一个字典的形式,因为Python不是MongoDBShell,没法直接识别出操作符,只能写成字符串形式1,即它的if,else,then三个key的顺序是无序的,这很可能直接导致$cond聚合条件不生效。
3、$group中似乎没法保留原字段不变,如果需要保留一些字段的话需要使用$max,$first,$last,$min这样的操作符来保留字段。
4、不到特殊情况,不建议使用group来聚合,因为像上面这样的聚合语句;比一次find加上多次distinct要慢很多。
5、$lookup的具体用法,直接参考 https://www.cnblogs.com/xuliuzai/p/10055535.html
6、聚合常见的优化方式:
- group中要聚合的字段(即要展示为_id的字段)需要增加索引。
- group之前可以通过project来减少聚合的范围。
- sort字段需要增加索引
- group应该尽量与limit联合使用,提高查找效率。