您好,登錄后才能下訂單哦!
前言
使用 pymongo 進行 group by 操作有兩種基本方式,他們都是 mongodb 的原生命令,于 Collection 對象上調用。
def aggregate(self, pipeline, **kwargs): def group(self, key, condition, initial, reduce, finalize=None, **kwargs):
示例數據
演示用的數據為一個訂單表,含有以下字段:
Order
_id: ObjectID
userid: int
itemid: int
amount: int
time: string
主要任務為:
即分別為:單鍵分組和多鍵分組
aggregate
聚合操作只接受一個列表類型的參數 —— pipeline。其每一個元素都是一步操作(stage)。全部可用的 stage 可參見:
https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#stages
注意 pipline 里面的 stage 是有序且可重復的,mongodb 會順序執行,因此一定要記得把像 $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 指定了返回數據的格式,其中 _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}, ...]
這里與單鍵分組的區別僅在于 _id 的類型,改成了一個字典,從而允許多鍵組合。
為了提高通用性,建議始終使用字典的格式。
另外,既然字符串和字典都可以做鍵,那么列表行不行呢?答案是不行,列表里的元素,(如 '$userid') 并不會被自動識別為字段,而是僅作一般字符串處理。
最后關于 aggregate 中可用的運算操作符,可參見:
https://docs.mongodb.com/manual/reference/operator/aggregation/#accumulators
如其中的 $addToSet 也是頗有用處,可以用來實現 “統計每個人都買過哪些 itemid” 這樣的功能:
group = { '_id': {'userid': '$userid'}, 'dist_itemids': {'$addToSet': '$itemid'}, }
group
相較于 aggregate 的全能,group 是專門處理分組操作的一個命令,因此這個方法的參數也更明確,主要參數為:
例:
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}, ...]
這里的分組數據聚合,是通過 reduce 函數實現的,這個函數與 python 的 reduce 不同,它不需要返回值,而是直接修改 prev 參數即可,這個參數會自動代入下一次調用。這可能是 js 的實現。
須注意的是 js 默認返回浮點數。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。