aggregate聚合是通過管道操作實現的。聚合管道里的每一步輸出,都會作為下一步的輸入,每一步在輸入文檔執行完操作后生成輸出文檔。
聚合管道:
$project
修改輸入文檔的結構。可以用來重命名、增加或刪除域,也可以用於創建計算結果以及嵌套文檔。對應project()
方法
$match
用於過濾數據,只輸出符合條件的文檔。$match使用MongoDB的標准查詢操作。對應match()
。
$limit
用來限制MongoDB聚合管道返回的文檔數。對應limit()
方法
$skip
在聚合管道中跳過指定數量的文檔,並返回余下的文檔。對應skip()
。
$unwind
將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值。對應unwind()
方法
$group
將集合中的文檔分組,可用於統計結果。對應group()
方法
$sort
將輸入文檔排序后輸出。對應sort()
方法
$geoNear
輸出接近某一地理位置的有序文檔。對應near()
。
$group
表達式說明:
$sum
計算總和
$avg
計算平均值
$min
獲取每一組集合中所有文檔對應值得最小值
$max
獲取每一組集合中所有文檔對應值得最大值
$push
在結果文檔中插入值到一個數組中
$addToSet
在結果文檔中插入值到一個數組中,但不創建副本
$first
根據資源文檔的排序獲取第一個文檔數據
$last
根據資源文檔的排序獲取最后一個文檔數據
舉例說明aggregate聚合 $group使用
商品屬性:_id, createTime, nowPriceL, nowPriceH, number
統計每一天內店鋪商品的最低價和最高價,平均最低價,
執行完$match管道后,得到的查詢結果會輸入到$project管道,執行完$project管道,得到的結果格式為{day,nowPriceL,nowPriceH},把這個結果輸入$group管道, $group管道執行完畢,輸出的結果輸入到$sort管道,$sort執行完畢,輸出最終結果集
Goods.aggregate([ { $match: { number: {$gte:100} //匹配number>=100的記錄 } }, { $project : { day : {$substr: [{"$add":["$createTime", 28800000]}, 0, 10] },//時區數據校正,8小時換算成毫秒數為8*60*60*1000=288000后分割成YYYY-MM-DD日期格式便於分組 "nowPriceL": 1, //設置原有nowPriceL為1,表示結果顯示原有字段nowPriceL "nowPriceH":1, //設置原有nowPriceH為1,表示結果顯示原有字段nowPriceH avgNowPriceL:{$toDouble:"$nowPriceL"},//把最低價轉換為小數 avgNowPriceH:{$toDouble:"$nowPriceH"},//把最高價轉換為小數 "dayNumber":1 //每組內有多少個成員 }, }, { $group: { _id:"$day", //按照$day進行分組(一組為1天) nowPriceL:{$min: "$nowPriceL"}, //查找組內最小的nowPriceL nowPriceH:{$max: "$nowPriceH"}, //查找組內最大的nowPriceH avgNowPriceL:{$avg:"$avgNowPriceL"},//統計每一天內店鋪商品的平均最低價 avgNowPriceH:{$avg:"$avgNowPriceH"},//統計每一天內店鋪商品的平均最高價 dayNumber:{$sum:1} } }, { $sort: { nowPriceL: 1//執行完 $group,得到的結果集按照nowPriceL升序排列 } }]).exec(function (err, goods){ //返回結果 console.log(goods); });
注意:
mongoodb存儲的數據是按照世界時間存儲的,因此進行分割操作時需要對時間進行時區校正,使用$add加上時區差8小時(毫秒數)才能得到正確的數據
$substr: [ <string>, <start>, <length> ] }
https://docs.mongodb.com/manual/reference/operator/aggregation/toDouble/#exp._S_toDouble