MongoDB不支持子查询,碰到这些复杂的运算就只能先将数据读出后再计算,而用Java等语言编写这类计算也不是很简单,这时可以考虑用esProc辅助实现。下面我们通过一个例子来看一下具体做法。
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的数据量较小,最终结果的数据量也较小。
用esProc协助MongoDB实现这个子查询的的脚本如下:
A1: 连接MongoDB数据库,ip和端口号是localhost:27017,数据库是test,用户名和密码都是test。
A2: 使用find函数从MongoDB中取数,形成游标。集合是orders,过滤条件是空,指定键_id不取出。esProc在find函数中采用了和MongoDB的find语句一样的参数格式。esProc的游标是分批读取和处理数据,可以避免数据量过大,内存出现溢出的情况。
A3: 取得employee中的数据,条件是STATE=”California”。
A4: 将A3(employee)中的EID排序。
A5: 按照条件过滤orders数据,条件是SELLERID必须在A4中,相当于SELLERID in A4。一次性取出结果。如果结果较大,也可以分批取出,比如取出前1000行:fetch(1000)。
计算结果是:
需要说明的是:esProc并不包含MongoDB的java驱动包。用esProc来访问MongoDB,必须提前将MongoDB的java驱动包(例如:mongo-java-driver-2.12.2.jar)放到[esProc安装目录]\common\jdbc中。
esProc协助MongoDB计算的脚本很容易集成到java中,只要增加一行,写成result A6即可向java输出resultset形式的结果,具体的代码参考esProc教程。同样,用java调用esProc访问MongoDB也必须将MongoDB的java驱动包放到java程序的classpath中。