Mongo使用聚合框架可以對集合中的文檔進行變換和組合。原理是用多個構件(篩選filtering、投射projecting、分組grouping、排序sorting、限制limiting、跳過skipping)創建一個管道(pipeline),用于對文檔的處理。
eg: db.articles.aggregate({"$project" : {"author" : 1}}, → 集中的文檔為{"_id":id,"author":author}
{"$group" : {"_id" : "$author", "count" : {"$sum" : 1}}}, → {"_id":author,"count":num}
{"sort" : {"count" : -1}}, → 對count字段降序處理
{"limit" : 5}); → 返回前五個
邏輯和運算的表達式
統計學生成績,出勤10%,平時分30%,期末成績60%,但如果免修則直接100分
db.student.aggregate(
{
"$project" : {
"grade" : {
"$cond" : [ →cond : [boolExpr, trueExpr, falseExpr] 如果bool為true就返回第二個,否者返回第三個參數
"$isExemption",
100,
{
"$add" : [
{"$multiply" : [.1, "$attendanceAvg"]},
{"$multiply" : [.3, "$quizzAvg"]},
{"$multiply" : [.6, "$testAvg"]}
]
}
]
}
}
});
MapReduce:靈活,能夠用js表達任意復雜的邏輯,但是非常慢,不應該用在實時的數據分析中。
1)映射(map):將操作映射到集合中的每個文檔。
2)洗牌(shuffle):按照鍵分組,并將產生的鍵值組成列表放到對應的鍵中。
3)化簡(reduce):把列表中的值化簡成一個單值。這個值被返回,然后接著洗牌,知道每個鍵的列表只有一個值為止,這個值也就是最終的結果。
這里舉一個給網頁分類的例子,有很多鏈接,每個鏈接都含有標簽(politics、geek等)用MapReduce找出最熱門的主題,熱門與否與時間也有關系。
map = function(){
for(let i in this.tags){ → 對每個標簽計算出分值
let recency = 1/(new Date() - this.date);
let score = recency * this.score;
emit(this.tags[i], {"urls": [this.url], "score": score});
}
};
化簡同一標簽的所有值,得到標簽的分數
reduce = function(key, emits){
let total = {urls: [], score: 0}; → reduce需要能在之前的map階段或者前一個reduce的結果上反復執行
for(let i in emits){ → 所以reduce返回的文檔必須能作為reduce的第二個參數的一個元素
emits[i].urls.forEach(url => {
total.urls.push(url);
})
total.score += emits[i].score;
}
return total;
}