MongoDB(Aggregation)


Aggregation

聚合(aggregate)指令可以操作一個(gè)集合中的文檔,將統(tǒng)計(jì)或處理部分的域, 再經(jīng)過加工后返回到客戶端,這些工作都是在服務(wù)器端完成的。如果是使用pipeline,通常就是按順序?qū)⒄麄€(gè)集合傳進(jìn)去,然后進(jìn)行加工處理,但是可以通過一些操作符在傳遞整個(gè)集合之前進(jìn)行篩選。pipline還可以得到index的支持。


Aggregation Pipeline 管道

Pipline Optimization 優(yōu)化操作

在執(zhí)行聚合的時(shí)候,其中有一個(gè)優(yōu)化的階段,通常就是通過調(diào)整操作符之間的相對順序來達(dá)到優(yōu)化的目的,比如下面這些典型的例子。

當(dāng)在aggregate時(shí)使用了$sort + $match 的時(shí)候,match在sort之前可能會(huì)減少一些集合的排序工作:
{ $match: { status: 'A' } },{ $sort: { age : -1 } }

當(dāng)在aggregate時(shí)使用了$skip + $limit的時(shí)候,limit在skip之前可能會(huì)減少一些工作量??紤]如下的順序:
{ $skip: 10 },{ $limit: 5 }
先忽略了前10個(gè),再取出5個(gè)。在執(zhí)行skip操作的時(shí)候,被操作的是被選中的所有文檔,最終我們才要了其中的5個(gè)。再考慮如下的順序:
{ $limit: 15 },{ $skip: 10 }
先限制返回的文檔最多只有15個(gè),然后再操作這15個(gè)文檔,進(jìn)行skip。相對來說,比上面的方式要快了。

優(yōu)化器還會(huì)執(zhí)行一些相對比較復(fù)雜的優(yōu)化操作。舉個(gè)例子,考慮如下的操作順序:
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }
先進(jìn)行編輯,再進(jìn)行匹配。這兩個(gè)操作似乎是有依賴的,因?yàn)榫庉嬃酥罂赡軙?huì)有一些field值的變動(dòng),會(huì)影響后面match的結(jié)果。為了優(yōu)化操作,可以先執(zhí)行一部分的匹配,減少選中的文檔,再進(jìn)行redact操作就可以減少了一些的時(shí)間啦。所以,優(yōu)化之后的樣子可能是這樣的:
{ $match: { year: 2014 } }, { $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }

Pipeline Limits 操作限制

自2.6開始,aggregate命令就可以返回一個(gè)cursor或者將結(jié)果存儲(chǔ)于一個(gè)集合中。每個(gè)文檔的大小是符合BSON大小限制的(16MB),若超過了這個(gè)限制就會(huì)產(chǎn)生error。這個(gè)限制僅針對于返回的文檔,而pipeline執(zhí)行的過程中可能會(huì)超過這個(gè)限制。

如果沒有指定要返回一個(gè)cursor或者是將結(jié)果存儲(chǔ)于一個(gè)集合中,那么MongoDB默認(rèn)返回一個(gè)包含結(jié)果的文檔,此時(shí)如果超出BSON大小限制的話就會(huì)產(chǎn)生錯(cuò)誤。

pipeline stage(翻譯為階段?)的內(nèi)存限制是100MB,一旦超過限制就會(huì)出錯(cuò)。那要是文件比較大呢?可以考慮allowDiskUse選項(xiàng),它會(huì)在必要時(shí)將臨時(shí)數(shù)據(jù)存儲(chǔ)到磁盤中去。


Map-Reduce 函數(shù)支持

mapreduce提供了一些aggregation pipline不支持的操作,使用起來更加靈活。它的樣子就跟一個(gè)函數(shù)一樣,返回的是文檔集合。
mapreduce操作可以將操作結(jié)果寫進(jìn)集合中或者僅僅返回結(jié)果,操作過程中可以執(zhí)行一連續(xù)的map、reduce等操作,對上一次的輸出進(jìn)行輸入。

Map-Reduce exampes 例子

假設(shè)有一個(gè)orders集合,每個(gè)文檔表示一個(gè)訂單,文檔大致如下所示:

{
     _id: ObjectId("50a8240b927d5d8b5891743c"),
     cust_id: "abc123",
     ord_date: new Date("Oct 04, 2012"),
     status: 'A',
     price: 25,
     items: [ { sku: "mmm", qty: 5, price: 2.5 },
              { sku: "nnn", qty: 5, price: 2.5 } ]
}

現(xiàn)在要查詢每個(gè)用戶一共支付了多少錢,這需要對每個(gè)訂單根據(jù)用戶id進(jìn)行分類,再對其中的price域,進(jìn)行求和


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容