協助 mongodb 計算之子查詢

【摘要】

      Mongodb 對錶數據的子查詢計算不如關係數據庫操作方便,但通過集算器 SPL 語言來實現就容易多了,不用再擔心 Mongodb 對子查詢的操作。

Mongodb日常開發中,經常會遇到兩個或多個數據表關聯的子查詢問題。若是關係數據庫,其中的子查詢大家相對比較熟悉,實現也比較容易。但Mongodb對子查詢的支持不夠友好,碰到這些複雜的運算就只能先將數據讀出後再計算,而用Java等語言編寫這類計算也不是很簡單。這時,我們可以考慮用集算器SPL語言輔助實現子查詢。SPL有豐富的接口及簡潔的語法,能夠極大地方便用戶使用Mongodb,讓子查詢書寫比較規範統一、效率高效,下面用例子說明。

       文檔orders保存了訂單數據,employee保存了員工數據,如下:

> db.orders.find();

{"_id" : ObjectId("5434f88dd00ab5276493e270"), "ORDERID" : 1, "CLIENT" : "UJRNP", "SELLERID" : 17, "AMOUNT" : 392, "ORDERDATE" : "2008/11/2 15:28" }

{"_id" : ObjectId("5434f88dd00ab5276493e271"), "ORDERID" : 2, "CLIENT" : "SJCH", "SELLERID" : 6, "AMOUNT" : 4802, "ORDERDATE" : "2008/11/9 15:28" }

{"_id" : ObjectId("5434f88dd00ab5276493e272"), "ORDERID" : 3, "CLIENT" : "UJRNP", "SELLERID" : 16, "AMOUNT" : 13500, "ORDERDATE" : "2008/11/5 15:28" }

{"_id" : ObjectId("5434f88dd00ab5276493e273"), "ORDERID" : 4, "CLIENT" : "PWQ", "SELLERID" : 9, "AMOUNT" : 26100, "ORDERDATE" : "2008/11/8 15:28" }

> db.employee.find();
{"_id" : ObjectId("5437413513bdf2a4048f3480"), "EID" : 1, "NAME" : "Rebecca", "SURNAME" : "Moore", "GENDER" : "F", "STATE" : "California", "BIRTHDAY" : "1974-11-20", "HIREDATE" : "2005-03-11", "DEPT" : "R&D", "SALARY" : 7000 }

{"_id" : ObjectId("5437413513bdf2a4048f3481"), "EID" : 2, "NAME" : "Ashley", "SURNAME" : "Wilson", "GENDER" : "F", "STATE" : "New York", "BIRTHDAY" : "1980-07-19", "HIREDATE" : "2008-03-16", "DEPT" : "Finance", "SALARY" : 11000 }

{"_id" : ObjectId("5437413513bdf2a4048f3482"), "EID" : 3, "NAME" : "Rachel", "SURNAME" : "Johnson", "GENDER" : "F", "STATE" : "New Mexico", "BIRTHDAY" : "1970-12-17", "HIREDATE" : "2010-12-01", "DEPT" : "Sales", "SALARY" : 9000 }

       要求查出訂單信息,其中訂單的SELLERID必須是employee集合中STATE= California的員工id。如果寫成sql就是:
       Select * from orders where orders.sellerid in (select eid from employee where employee.state=’ California’)。

       同時,Orders的數據量較大無法一次取出,而employee的數據量較小,最終結果的數據量也較小。
       使用集算器SPL的代碼如下:


A
1=mongo_open("mongodb://localhost:27017/test?user=test&password=test")
2=mongo_shell(A1,"orders.find(,{_id:0})")
3=mongo_shell(A1,"employee.find({STATE:'California'},{_id:0})").fetch()
4=A3.(EID).sort()
5=A2.select(A4.pos@b(SELLERID)).fetch()
6>mongo_close(A1)

A1: 連接MongoDB,連接字格式爲mongo://ip:port/db?arg=value&…。
A2: 使用find函數從orders中取數,形成遊標,過濾條件是空,指定鍵_id不取出。SPL的遊標是分批讀取和處理數據,可以避免數據量過大,以防內存溢出。
A3: 取得employee中的數據,條件是STATE="California"。
A4: 將A3(employee)中的EID排序。
A5: 按照條件過濾orders數據,條件是SELLERID必須在A4中,相當於SELLERID in A4。其中,函數pos實現過濾條件,檢測order的SELLERID值是否存在於employee的EID中。這裏一次性取出所有數據結果,如果結果較大,也可以分批取出,比如取出前1000行:fetch(1000)。
計算結果是:                                              65a078d9f670485f96aa46ea3952d795_mongo_100.png
A6: 關閉Mongodb連接。

      這個例子中,A2,A3獲取兩表相關的數據,A5中的select獲取符合條件的數據,實現表的子查詢。

      需要說明的是:集算器esProc並不包含mongodb的java驅動包。如果要用esProc訪問mongodb,必須提前將mongodb的java驅動包(例如:mongo-java-driver-2.12.2.jar)放到集算器設置的外部庫目錄extLib\MongoCli下。

      除了在集算器中直接計算,上述使用SPL協助mongodb計算的腳本也很容易集成到java中,只要增加一行,寫成return A5即可向java輸出resultset形式的結果,具體的代碼參考esProc教程。同樣,用java調用esProc訪問mongodb也必須將mongdb的java驅動包放到java程序的classpath中。


相關文章:
MongoDB 連接運算   
MongoDB 外鍵關聯   
MongoDB 本地化排序   
MongoDB 子查詢     
MongoDB 分組統計    
MongoDB 分組 topN    
MongoDB 關聯運算   
MongoDB 子文檔 List 字段 
協助 MongoDB 計算之交叉彙總 
將 MongoDB 導出成 csv  
協助報表開發之 MongoDB join


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