協助報表開發之 MongoDB join

摘要】

      集算器 SPL 語言支持多樣性數據源,通過 SPL 對 MongoDB 多個集合進行 join 關聯,不僅簡化了對 MongoDB 數據的操作,而且有利於與其它報表工具的方便集成。

處理多樣性數據源是報表開發中的常見問題,而常見的 JasperReport 等報表工具本身卻難以應付,比如展現兩個 MongoDB 集合連接的結果。雖然 JasperReport 有 virtual data source 或 table join,但這些功能只在商業版或高端版本出現,在免費版中實現的難度很大。而且這些功能只支持兩個數據源的連接,要實現多連接則麻煩得多。另外,這些功能只能基於圖形化界面操作,對連接後的數據無法進行類似 SQL 的結構化計算。

       集算器 SPL 語言具有面向結構化處理的強計算引擎,支持多樣性數據源,集成簡單,可以協助不同報表工具方便地實現此類需求,下面用例子說明。

       Sales和 emp 是 MongoDB 中的兩個集合,sales 中的字段 SellerId 邏輯上相當於外鍵,指向 emp 的 EId 字段,現在需要按時間段查詢出 sales 中的訂單,並和 emp 進行左連接,最後在報表中展現。部分源數據如下:

   集合sales

OrderIDClientSellerIdAmountOrderDate
26TAS12142.42009-08-05
27HP13538.62010-08-06
28DY11307.22010-08-07
29WVF194202010-08-08
30UFS181200.82009-08-09
31SWFR151488.82010-08-12
32JFS34682009-08-13

集合emp

EIdStateDeptNameGenderSalaryBirthday
2New YorkFinanceAshleyF110011980-07-19
3New MexicoSalesRachelF90001970-12-17
4TexasHREmilyF70001985-03-07
5TexasR&DAshleyF160001975-05-13
6CaliforniaSalesMatthewM110001984-07-07
7IllinoisSalesAlexisF90001972-08-16

使用集算器SPL的代碼如下:


A
1=mongo_open("mongodb://localhost:27017/test?user=root&password=sa")
2=mongo_shell(A1,"sales.find({$and:[{OrderDate:{$gte:'"+string(begin)+"'}},{  OrderDate:{ $lte:'"+string(end)+"'}} ] },{_id:0} )").fetch()
3=mongo_shell(A1,"emp.find(,,"{_id:0}").fetch()
4>mongo_close(A1)
5=join@1(A2:sales,SellerId;A3:emp,EId)
6=A5.new(sales.OrderID:OrderID,sales.Client:Client,sales.Amount:Amount,sales.OrderDate:OrderDate,emp.Name:Name,emp.Dept:Dept,emp.Gender:Gender)
7result   A6

A1: 連接 MongoDB,連接字格式爲 mongo://ip:port/db?arg=value&…

A2: 使用 find 函數從集合 sales 中查詢出某時間段的記錄,取出 _id 之外的所有字段。其中查詢條件中的 begin 和 end 是來自報表的外部參數,分別表示 OrderDate 的起始時間和終止時間。

函數 find 返回的是遊標,並不會把數據直接讀入內存,因此能夠很好地支持大數據量。類似的,還可以用 skip、sort、conj 等函數繼續操作遊標,直到遇到函數 fetch、groups,或語句 for 時纔會真正取數。本例直接用函數 fetch() 將數據讀入內存,假如時間段是 2009-01-01 到 2009-12-31,則 A2 的計算結果如下:

a_100png

A3: 使用 find 函數從集合 carInfo 中取數,形成遊標。過濾條件是空,取出 _id 之外的所有字段,結果如下:

a_101png

A4: 關閉 MongoDB。

A5: 將 A2 和 A3 進行左連接,連接字段是 A2 的 SellerId 和 A3 的 Eld,直觀起見,連接後的兩部分數據分別命名爲 sales 和 emp。函數 join 執行連接計算,選項 @1 表示左連接,計算結果如下圖左側:

a_102png

可以看到,由於是左連接,因此 sales 中部分 SellerId 無法在 emp 中找到對應的記錄。如果想進行全連接,可以使用選項 @f,無選項則表示內連接。

A6: 執行連接操作,從連接的結果中取出需要的字段,並用函數 new 組成二維表。比如sales.OrderID:OrderID表示從 A5 取出 sales.OrderID 字段,重命名爲 OrderID(報表工具無法識別 sales.OrderID 這樣的字段名)。計算結果如下:

a_103png

到此爲止,報表需要的數據就全部計算出來了。
A7: 將 A6 中的二維表返回報表工具。
集算器對外提供 JDBC 接口,報表工具會將集算器識別爲普通數據庫,集成方案請參考相關文檔。

接下來以 JasperReport 爲例設計報表,表樣如下:

a_104png

 需要定義兩個報表參數 Pbegin、Pend,分別對應集算器中的兩個參數。預覽後可以看到報表結果:

a_105png

       報表調用集算器的方法和調用存儲過程一樣,此例中可以將本腳本保存爲 mongodbJoin.dfx,在 JasperReport 的 SQL 設計器中可以用mongodbJoin $P{pbegin},$P{pend}來調用。

       簡言之,SPL 從 MongoDB 獲取多個集合數據後,將它們通過 join 函數進行連接計算,再通過函數 new 按需求將數據生成序表,供其它的報表工具展示。通過 SPL 對多個集合進行 join 關聯,大大簡化了對 MongoDB 數據的操作,有利於與其它報表工具的方便集成。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章