pymongo中g(shù)roup by的操作方法教程
前言
使用 pymongo 進行 group by 操作有兩種基本方式,他們都是 mongodb 的原生命令,于 Collection 對象上調(diào)用。
def aggregate(self, pipeline, **kwargs): def group(self, key, condition, initial, reduce, finalize=None, **kwargs):
示例數(shù)據(jù)
演示用的數(shù)據(jù)為一個訂單表,含有以下字段:
Order
_id: ObjectID
userid: int
itemid: int
amount: int
time: string
主要任務(wù)為:
- 統(tǒng)計某個時間區(qū)間內(nèi)每個 userid 的訂單數(shù)
- 統(tǒng)計某個時間區(qū)間內(nèi)每組 (userid, itemid) 共售出多少 amount
即分別為:單鍵分組和多鍵分組
aggregate
聚合操作只接受一個列表類型的參數(shù) —— pipeline。其每一個元素都是一步操作(stage)。全部可用的 stage 可參見:
https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#stages
注意 pipline 里面的 stage 是有序且可重復(fù)的,mongodb 會順序執(zhí)行,因此一定要記得把像 $match 這樣的 stage 放前面。
單鍵分組
start_time = '2010-10-10 00:00:00' end_time = '2010-10-10 23:59:59' match = { 'time': { '$gte': start_time, '$lte': end_time, } } groupby = 'userid' group = { '_id': "$%s" % (groupby if groupby else None), 'count': {'$sum': 1} } ret = collection.aggregate( [ {'$match': match}, {'$group': group}, ] ) >>> ret [{'_id': 123, 'count': 500}, ...]
$group 指定了返回數(shù)據(jù)的格式,其中 _id 字段是分組的鍵。
多鍵分組
groupby = ['itemid', 'userid'] group = { '_id': {key: ('$%s' % key) for key in groupby} or {'None': '$None'}, 'count': {'$sum': '$amount'} } ret = collection.aggregate( [ {'$match': match}, {'$group': group}, ] ) >>> ret [{'_id': {'itemid': 111, 'user_id': 123}, 'count': 100}, ...]
這里與單鍵分組的區(qū)別僅在于 _id 的類型,改成了一個字典,從而允許多鍵組合。
為了提高通用性,建議始終使用字典的格式。
另外,既然字符串和字典都可以做鍵,那么列表行不行呢?答案是不行,列表里的元素,(如 '$userid') 并不會被自動識別為字段,而是僅作一般字符串處理。
最后關(guān)于 aggregate 中可用的運算操作符,可參見:
https://docs.mongodb.com/manual/reference/operator/aggregation/#accumulators
如其中的 $addToSet 也是頗有用處,可以用來實現(xiàn) “統(tǒng)計每個人都買過哪些 itemid” 這樣的功能:
group = { '_id': {'userid': '$userid'}, 'dist_itemids': {'$addToSet': '$itemid'}, }
group
相較于 aggregate 的全能,group 是專門處理分組操作的一個命令,因此這個方法的參數(shù)也更明確,主要參數(shù)為:
- key list, 分組的鍵
- condition dict,過濾條件
- initial dict,初始值
- reduce string/bson.Code, js 的 reduce 函數(shù)
例:
key = ['userid', 'itemid'] condition = { 'time': { '$gte': start_time, '$lte': end_time, } } initial = {'count': 0} reducer = Code(""" function(obj, prev) { prev.count = prev.count + obj.amount } """) ret = collection.group(key, condition, initial, reducer) >>> ret [{'userid': 110, 'itemid': 123, 'count': 500.0}, ...]
這里的分組數(shù)據(jù)聚合,是通過 reduce 函數(shù)實現(xiàn)的,這個函數(shù)與 python 的 reduce 不同,它不需要返回值,而是直接修改 prev 參數(shù)即可,這個參數(shù)會自動代入下一次調(diào)用。這可能是 js 的實現(xiàn)。
須注意的是 js 默認返回浮點數(shù)。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,謝謝大家對腳本之家的支持。
相關(guān)文章
Python使用metaclass實現(xiàn)Singleton模式的方法
這篇文章主要介紹了Python使用metaclass實現(xiàn)Singleton模式的方法,實例分析了Python基于metaclass實現(xiàn)單例模式的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-05-05python編程之requests在網(wǎng)絡(luò)請求中添加cookies參數(shù)方法詳解
這篇文章主要介紹了python編程之requests在網(wǎng)絡(luò)請求中添加cookies參數(shù)方法詳解,具有一定參考價值,需要的朋友可以了解下。2017-10-10使用Python的Treq on Twisted來進行HTTP壓力測試
這篇文章主要介紹了使用Python的Treq on Twisted來進行HTTP壓力測試,基于Python中的Twisted框架,需要的朋友可以參考下2015-04-04python深度學(xué)習借助多標簽分類器進行對抗訓(xùn)練
這篇文章主要為大家介紹了python深度學(xué)習中如何借助多標簽分類器進行對抗訓(xùn)練,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-01-01解決python訓(xùn)練模型報錯:BrokenPipeError:?[Errno?32]?Broken?pipe
這篇文章主要介紹了解決python訓(xùn)練模型報錯:BrokenPipeError:?[Errno?32]?Broken?pipe問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07