mongodb聚合查询优化_MongoDB聚合查询详解
聚合操作主要用于處理數(shù)據(jù)并返回計算結(jié)果。聚合操作將來自多個文檔的值組合在一起,按條件分組后,再進(jìn)行一系列操作(如求和、平均值、最大值、最小值)以返回單個結(jié)果。
MongoDB 提供了三種執(zhí)行聚合的方法:聚合管道、map-reduce 和單一目標(biāo)聚合方法,本節(jié)只介紹前兩種方法。
聚合管道方法
MongoDB 的聚合框架就是將文檔輸入處理管道,在管道內(nèi)完成對文檔的操作,最終將文檔轉(zhuǎn)換為聚合結(jié)果。
最基本的管道階段提供過濾器,其操作類似查詢和文檔轉(zhuǎn)換,可以修改輸出文檔的形式。其他管道操作提供了按特定字段對文檔進(jìn)行分組和排序的工具,以及用于聚合數(shù)組內(nèi)容(包括文檔數(shù)組)的工具。
此外,在管道階段還可以使用運算符來執(zhí)行諸如計算平均值或連接字符串之類的任務(wù)。聚合管道可以在分片集合上運行。
聚合管道方法的流程參見下圖。
上圖的聚合操作相當(dāng)于 MySQL 中的以下語句:
select cust_id as _id, sum(amount) as total from orders where status like "%A%" group by cust_id;
MongoDB 中的聚合操作語法如下:
db.collection.aggregate([
{
$match : {< query >},
}
{
$group: {< fieldl >: < field2 >}
}
])
Query 設(shè)置統(tǒng)計查詢條件,類似于 SQL 的 where,field1 為分類字段,要求使用 _id 名表示分類字段,field2 為包含各種統(tǒng)計操作符的數(shù)字型字段,如 $sum、$avg、$min 等。
這個語法看起來比較難以理解,下面給出一個示例進(jìn)行對照:
db.mycol.aggregate([
{
$group : {_id : "$by_user", num_tutorial : {$sum : 1}}
}
])
相當(dāng)于MySQL中的:
select by_user as _id, count(*) as num_tutorial from mycol group by by_user;
再舉一個復(fù)雜的例子,按照指定條件對文檔進(jìn)行過濾,然后對滿足條件的文檔進(jìn)行統(tǒng)計,并將統(tǒng)計結(jié)果輸出到臨時文件中。
首先插入多條文檔,代碼如下:
db.articles.insert([
{ "_id" : 10, "author" : "dave", "score" : 80, "views" :100 },
{ "_id" : 11, "author" : "dave", "score" : 85, "views" : 521 },
{ "_id" : 12, "author" : "ahn", "score" : 60, "views" : 1000 },
{ "_id" : 13, "author" : "li", "score" : 55, "views" : 5000 },
{ "_id" : 14, "author" : "annT", "score" : 60, "views" : 50 },
{ "_id" : 15, "author" : "1i", "score": 94, "views": 999 },
{ "_id" : 16, "author" : "ty", "score" : 95, "views": 1000 }
]);
再進(jìn)行聚合分類統(tǒng)計,代碼如下:
db.articles.aggregate([
{
$match: { $or: [{ score: { $gt: 70, $1t: 90 }}, { views: { $gte: 1000 }}]}}, { $group: { _id: null, count: { $sum: 1 }}
}
]);
最終統(tǒng)計結(jié)果為:
{ "_id" : null, "count" : 5 }
管道階段的 RAM 限制為 100MB。若要允許處理大型數(shù)據(jù)集,則可使用 allowDiskUse 選項啟用聚合管道階段,將數(shù)據(jù)寫入臨時文件。
map-reduce 方法
MongoDB 還提供了 map-reduce 方法來執(zhí)行聚合。通常 map-reduce 方法有兩個階段:首先 map 階段將大批量的工作數(shù)據(jù)分解執(zhí)行,然后 reduce 階段再將結(jié)果合并成最終結(jié)果。
與其他聚合操作相同,map-reduce 可以指定查詢條件以選擇輸入文檔以及排序和限制結(jié)果。
map-reduce 使用自定義 JavaScript 函數(shù)來執(zhí)行映射和減少操作,雖然自定義 JavaScript 與聚合管道相比提供了更大的靈活性,但通常 map-reduce 比聚合管道效率更低、更復(fù)雜。
map-reduce 可以在分片集合上運行,也可以輸出到分片集合。map-reduce 的語法如下:
>db.collection.mapReduce(
function() { emit(key,value); },
function(key, values) { return reduceFunction }
{ query: document, out: collection }
)
參數(shù)說明:
function() { emit(key,value); } 為 map 映射函數(shù),負(fù)責(zé)生成鍵值對序列,并作為 reduce 函數(shù)輸入?yún)?shù)。
function(key, values) { return reduceFunction } 為 reduce 統(tǒng)計函數(shù),reduce 函數(shù)的任務(wù)就是將 key-values 變成 key-value,也就是把 values 數(shù)組轉(zhuǎn)換成一個單一的值 value。
query 設(shè)置篩選條件,只有滿足條件的文檔才會調(diào)用 map 函數(shù)。
out 為統(tǒng)計結(jié)果的存放集合,如果不指定則使用臨時集合,但會在客戶端斷開后自動刪除。
舉例說明使用 map-Teduce 方法進(jìn)行 MongoDB 文檔數(shù)據(jù)的聚合。首先插入數(shù)據(jù),數(shù)據(jù)為每位顧客 cust_id 的消費情況,代碼如下:
db.order.insert([
{ "cust_id" : "l", "status" : "A", "price" : 25, "items" : [{"sku" : "mmm", "qty" : 5, "price" : 2.5 },
{ "sku" : "nnn", "qty" : 5, "price" : 2.5 }]},
{ "cust_id" : "l", "status" : "A", "price" : 25, "items" : [{"sku" : "mmm", "qty" : 5, "price" : 2.5 },
{ "sku" : "nnn", "qty" : 5, "price" : 2.5 }]},
{ "cust_id" : "2", "status" : "A", "price" : 25, "items" : [{"sku" : "mmm", "qty" : 5, "price" : 2.5 },
{ "sku" : "nnn", "qty" : 5, "price" : 2.5 }]},
{ "cust_id" : "3", "status" : "A", "price" : 25, "items" : [{"sku" : "mmm", "qty" : 5, "price" : 2.5 },
{ "sku" : "nnn", "qty" : 5, "price" : 2.5 }]},
{ "cust_id" : "3", "status" : "A", "price" : 25, "items" : [{"sku" : "mmm", "qty" : 6, "price" : 2.5 },
{ "sku" : "nnn", "qty" : 6, "price" : 2.5 }]},
])
編寫 map 函數(shù),cust_id 作為 map 的輸出 key,price 作為 map 的輸出 value,代碼如下:
var mapFunc = function(){
emit(this.cust_id, this.price);
};
編寫 reduce 函數(shù),將相同的 map 的輸出 key(cust_id) 聚合起來,這里對輸出的 value 進(jìn)行 sum 操作,代碼如下:
var reduceFunc = function(key,values){
return Array.sum(values);
};
執(zhí)行 map-reduce 任務(wù),將 reduce 的輸出結(jié)果保存在集合 map_result_result 中,代碼如下:
db.order.mapReduce(mapFunc, reduceFunc, { out: { replace: 'map_result_result' }})
查看當(dāng)前數(shù)據(jù)庫下的所有集合,會發(fā)現(xiàn)新建了一個 map_result_result,此集合里保存了 map-reduce 聚合后的結(jié)果:
>show collections
map_result_result
myColl
order
>db.map_result_result.find()
{ "_id" : "l", "value" : 50.0 }
{ "_id" : "2", "value" : 25.0 }
{ "_id" : "3", "value" : 55.0 }
總結(jié)
以上是生活随笔為你收集整理的mongodb聚合查询优化_MongoDB聚合查询详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xshell 安装yum_Xshell上
- 下一篇: staruml无法打开mdj文件_Sta