MongoDB 不支持 join, 其官网上推荐的 unity jdbc 可以把数据取出来进行二次计算实现 join 运算, 但收费版才有这个功能. 其他免费的 jdbc drive 只能支持最基本的 SQL 语句, 不支持 join. 如果用 Java 等编程语言将数据取出后实现 join 计算, 也比较复杂.
3,esProc
用免费的 esProc 配合 MongoDB, 可以实现 join 计算. 这里通过一个例子来说明一下具体作法.
MongoDB 中的文档 orders 保存了订单数据, employee 保存了员工数据. 如下:
- MongoDB shell version: 2.6.4
- connecting to: test
- > 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-1
1-20″, "HIREDATE" : "2005-03-11″,"DEPT":"R&D","SALARY" : 7000 }
- {
- "_id" : ObjectId("5437413513bdf2a4048f3481″),"EID": 2,"NAME":"Ashley","S
- URNAME":"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","S
- URNAME":"Johnson","GENDER":"F","STATE":"New Mexico","BIRTHDAY":"1970-
12-17″, "HIREDATE" : "2010-12-01″,"DEPT":"Sales","SALARY" : 9000 }
...
Orders 中的 sellerid 对应 employee 中的 eid. 需要查询出 employee 的 state 属性等于 California 的所有订单信息. 其中 orders 数据量较大, 不能一次装入内存. Employee 数据量较小, Orders 过滤之后的结果数据量也比较小.
查询条件表达式可以作为参数传递给 esProc, 如下图:
A1: 连接 MongoDB 数据库, ip 和端口号是 localhost:27017, 数据库是 test, 用户名和密码都是 test.
A2: 使用 find 函数从 MongoDB 中取数, 形成游标. 集合是 orders, 过滤条件是空, 指定键_id 不取出. esProc 在 find 函数中采用了和 mongdb 的 find 语句一样的参数格式. esProc 的游标支持分批读取和处理数据, 可以避免数据量过大, 内存出现溢出的情况.
A3: 取得 employee 中的数据. 因为数据量不大, 所以用 fetch 函数一次取出.
A4: 使用 switch 函数, 将游标 A2 中 SELLERID 字段的值, 转换为 A3(employee)中的记录引用.
A5: 按照条件过滤. 这里使用宏来实现动态解析表达式, 其中的 where 就是传入参数. 集算器将先计算 ${...}里的表达式, 将计算结果作为宏字符串值替换 ${...}之后解释执行. 这个例子中最终执行的是:=A4.select(SELLERID.STATE=="California"). 由于 SELLERID 已经转化为 employee 的对应记录的引用, 所以可以直接写 SELLERID.STATE. 过滤之后的结果数据量较小, 所以一次取出. 如果结果数据量仍然比较大的话, 可以分批取出, 比如每次取出 10000 条: fetch(10000).
A6: 将过滤结果中的 SELLERID 重新切换为普通值.
A6 的计算结果是:
过滤条件发生变化时不用改变程序, 只需改变 where 参数即可. 例如, 条件变为: state 等于 California 的订单, 或者 CLIENT 等于 PWQ 的订单. Where 的参数值可以写为: CLIENT=="PWQ"|| SELLERID.STATE=="California".
esProc 并不包含 MongoDB 的 java 驱动包. 用 esProc 来访问 MongoDB, 必须提前将 MongoDB 的 java 驱动包 (esProc 要求 2.12.2 或以上版本的驱动, mongo-java-driver-2.12.2.jar) 放到[esProc 安装目录]\common\jdbc 中.
esProc 协助 MongoDB 计算的脚本很容易集成到 java 中, 只要增加一行 A7, 写成 result A6 即可向 java 输出 resultset 形式的结果, 具体的代码请参考 esProc 教程. 同样, 用 java 调用 esProc 访问 MongoDB 也必须将 mongdb 的 java 驱动包放到 java 程序的 classpath 中.
来源: http://www.bubuko.com/infodetail-3052515.html