MongoDB 分組統(tǒng)計

【摘要】

MongoDB 在進行分組統(tǒng)計時如果面對一些比較復雜的計算情況,往往會遇到 shell 腳本過于復雜的問題。而集算器 SPL 語言,則因其有豐富的函數庫及易用性恰好能彌補 Mongo 這方面的不足。若想了解更多,請前往乾學院:MongoDB 分組統(tǒng)計!

???????MongoDB 作為 NoSql 文檔型數據庫,在全球范圍得到廣泛的支持與應用。在比較常用的數據庫功能中,相對于普通的增刪改查,使用 group 聚合分組統(tǒng)計有些復雜,而 MongoDB 也給予了支持。本文將對MongoDb分組的實現方法及示例進行分析,通過在 MongoDB 腳本中操作、使用集算器 SPL 語言操作兩種操作途徑,進行簡單的歸納總結。具體的問題場景包括以下幾個方面:

1. 內嵌數組結構的統(tǒng)計

2. 內嵌文檔求和

3. 分段分組結構統(tǒng)計

4. 多字段分組統(tǒng)計

1. 內嵌數組結構的統(tǒng)計

對嵌套數組結構中的數據進行統(tǒng)計處理例如查詢考試科目的平均分及每個學生的總成績:

測試數據:


期待統(tǒng)計結果:


Mongodb腳本:


由于各科分數 scroe 是按課目、成績記錄的數組結構,統(tǒng)計前需要將它拆解,將每科成績與學生對應,然后再實現分組計算。這需要熟悉 unwind 與 group 組合的應用。

SPL 腳本 (student.dfx):


按課目統(tǒng)計的總分數:


每個學生的總成績:


腳本說明:

A1:連接 mongodb 數據庫。

A2:獲取 student 表中的數據。

A3:將 scroe 數據合并成序表,再按課程分組,計算平均分。

A4:統(tǒng)計每個學生的成績后返回列名為 NAME、TOTAL 的序表。new 函數表示生成新序表。

A5:關閉數據庫連接。

???????這個嵌套結構統(tǒng)計的例子比較常見,相信很多人都遇到過,需要先拆解再分組計算,主要是熟悉 mongodb 對嵌套數據結構的處理。

2. 內嵌文檔求和

對內嵌文檔中的數據求和處理, 例如統(tǒng)計下面每條記錄中 income,output 的數量和。

測試數據:


期待統(tǒng)計結果:


Mongodb腳本:

var fields = [? "income", "output"];

db.computer.aggregate([

? ?? {

? ????? $project:{

? ???????? "values":{

? ??????????? $filter:{??

?????????????? input:{

? ????????????????? ? "$objectToArray":"$$ROOT"?

????????????? },?

????????????? cond:{?

?????????????????? $in:[?

????????????????????? "$$this.k",

? ? ? ? ? ? ? ? ? ? ? fields

????????????????? ]?

????????????? }?

?????????? }?

????? ??}?

???? }?

? },?

? {

? ????? $unwind:"$values"?

? },?

? {?

?????? $project:{

? ???????? key:"$values.k",?

? ? ? ? ? values:{?

???????????? "$sum":{?

??????????????? "$let":{?

?????????????????? "vars":{? ?

??????????????????? "item":{? ?

?????????????????????? ? "$objectToArray":"$values.v"?

??????????????????? }?

???????????????? },?

?? ? ? ? ? ? ? ? ? "in":"$$item.v"?

????????????? }?

?????????? }?

??????? }

????? }

?? },

?? {$sort: {"_id":-1}},?

? { "$group": {?

?? "_id": "$_id",

??? 'income':{"$first": ? "$values"},

??? "output":{"$last": ? "$values"}?

?? }},

]);?

filter將income,output 部分信息存放到數組中,用 unwind 拆解成記錄,再累計各項值求和,按 _id 分組合并數據。

SPL腳本:


統(tǒng)計結果


腳本說明:

A1:連接數據庫

A2:獲取 computer 表中的數據

A3:將 income、output 字段中的數據分別轉換成序列求和,再與 ID 組合生成新序表

A4:關閉數據庫連接。

??????獲取子記錄的字段值,然后求和,相對于 mongo 腳本簡化了不少。這個內嵌文檔與內嵌數組在組織結構上有點類似,不小心容易混淆,因此需要特別注意與上例中的 scroe 數組結構比較,寫出的腳本有所不同。

3. 分段分組結構統(tǒng)計

統(tǒng)計各段內的記錄數量。例如下面按銷售量分段,統(tǒng)計各段內的數據量,數據如下:


分段方法:0-3000;3000-5000;5000-7500;7500-10000;10000 以上。

期望結果:


Mongo 腳本


這個需求按條件分段分組,mongodb 沒有提供對應的 api,實現起來有點繁瑣,上面的程序是其中實現的一個例子參考,當然也可以寫成其它實現形式。下面看看集算器腳本的實現。

SPL腳本:


腳本說明:

A1:定義 SALES 分組區(qū)間。

A2:連接 mongodb 數據庫。

A3:獲取 sales 表中的數據。

A4:根據 SALES 區(qū)間分組統(tǒng)計員工數。其中函數 pseg()表示返回成員在序列中的區(qū)段序號,int() 表示轉換成整數。

A5:關閉數據庫連接。

?????? Mongodb腳本與 SPL 腳本都實現了預期的結果,但函數pseg 的使用讓 SPL 腳本精簡了不少。

4. 多字段分組統(tǒng)計

統(tǒng)計分類項下的總數及各子項數。下面統(tǒng)計按 addr 分類的 book 的數量以及其下不同 book 類型的數量。


期望結果:


Mongo腳本


先按 addr,book 分組統(tǒng)計 book 數,再按 addr 分組統(tǒng)計 book 數,調整顯示順序。

SPL腳本 (books.dfx):


計算結果:


腳本說明:

A1:連接 mongodb 數據庫。

A2:獲取 books 表中的數據。

A3:按 addr,book 分組統(tǒng)計 book 數顧。

A4:再按 addr 分組統(tǒng)計 book 數。

A5:將 A4 中的 Total 按 addr 關聯后合并到序表中。

B5: 返回序表 A5。

A6:關閉數據庫連接。

????????這個例子中的 SPL 腳本除了一如既往的精簡清晰外,還顯示了如何簡單方便地與 Java 程序集成。

在 Java 程序中如果要對 MongoDB 實現上面的分組統(tǒng)計功能,需要根據不同的需求重新一五一十地實現,比較麻煩的同時也不通用。而如果用集算器來實現就容易多了,集算器提供了 JDBC 驅動程序,支持在 Java 程序中用 JDBC 存儲過程方式訪問計算結果,調用方法與調用存儲過程相同。(JDBC 具體配置參考《集算器教程》中的“JDBC基本使用”章節(jié))?

Java 調用主要過程如下:

public void testStudent (){

Connection con = null;

com.esproc.jdbc.InternalCStatement st;

try{

// 建立連接

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");

//調用存儲過程,其中books是 dfx 的文件名

st =(com. esproc.jdbc.InternalCStatement)con.prepareCall("call books ()");

//執(zhí)行存儲過程

st.execute();

// 獲取結果集

ResultSet rs = st.getResultSet();

。。。。。。。

catch(Exception e){

System.out.println(e);

}

???????可以看到,集算器的計算結果能夠很方便地供 Java 應用程序使用。除了上面的調用方式,程序也可以修改成直接加載 SPL 腳本的函數,用 SPL 腳本文件名當參數來實現。同時,集算器也支持 ODBC 驅動,與其它支持 ODBC 的語言集成也與此類似。

???????簡單總結一下,MongoDB 的聚合分組計算的操作與存儲文檔的結構息息相關,豐富的文檔結構一方面有利于存儲,同時數據查詢展示也可以做到多樣化,但另一方面也帶來了 shell 腳本操作的復雜性,寫起來比較不容易, 需要考慮的細節(jié)、步驟也比較多。通過上面這幾個簡單案例的分析比較,可以看到集算器 SPL 在實現分組統(tǒng)計方面能簡化操作,降低難度,從而有效地幫助我們解決問題。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容