你的位置:首页 > 数据库

[数据库]集算器协助java处理多样性数据源之MongoDB


MongoDB不支持join,其官网上推荐的unity jdbc可以把数据取出来进行二次计算实现join运算,但这些join、group、函数、表达式等高级功能都是收费版才有,而且即使是收费版本,对子查询、窗口函数等复杂SQL运算仍不支持。其他免费的jdbc drive就只能支持最基本的SQL语句了。

用免费的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的所有订单信息。查询条件表达式可以作为参数传递给esProc,如下图:

 

esProc并不包含MongoDB的java驱动包。用esProc来访问MongoDB,必须提前将MongoDB的java驱动包(esProc要求2.12.2或以上版本的驱动,mongo-java-driver-2.12.2.jar)放到[esProc安装目录]\common\jdbc中。Mongodb的java驱动包下载地址是:https://github.com/mongodb/mongo-java-driver/releases。

esProc的程序代码如下:

A1: 连接MongoDB数据库,ip和端口号是localhost:27017,数据库是test,用户名和密码都是test。如果需要其他参数的话可以按照mongo://ip:port/db?arg=value&…格式继续写参数。

A2: 使用find函数从MongoDB中取数,形成游标。集合是orders,过滤条件是空,指定键_id不取出。可以看出find函数和MongoDB的find函数类似。esProc的游标是分批读取和处理数据,可以避免数据量过大,内存出现溢出的情况。这里数据量不大,所以用fetch函数一次取出。

A3: 取得employee中的数据。

A4: 使用switch函数,将A2(orders)中SELLERID字段的值,转换为A3(employee)中的记录引用。

A5: 按照条件过滤。这里使用宏来实现动态解析表达式,其中的where就是传入参数。集算器将先计算${…}里的表达式,将计算结果作为宏字符串值替换${…}之后解释执行。这个例子中最终执行的是:=A2.select(SELLERID.STATE=”California”)。由于SELLERID已经转化为employee的对应记录的引用,所以可以直接写SELLERID.STATE。

A6:将过滤结果中的SELLERID重新切换为普通值。

A7:将符合条件的结果集返回给java。

过滤条件发生变化时不用改变程序,只需改变where参数即可。例如,条件变为:state等于California的订单,或者CLIENT等于PWQ的订单。Where的参数值可以写为:CLIENT==”PWQ”|| SELLERID.STATE==”California”。

在Java程序中使用esProc JDBC调用这段程序获得结果的代码如下:(将上述esProc程序保存为test.dfx,将MongoDB的java驱动包放到java程序的classpath中):

    //建立esProc jdbc连接
    Class.forName(“com.esproc.jdbc.InternalDriver”);
    con= DriverManager.getConnection(“jdbc:esproc:local://”);
    //调用esProc程序(存储过程),其中test是dfx的文件名
    com.esproc.jdbc.InternalCStatement st =(com.esproc.jdbc.InternalCStatement)con.prepareCall(“call test(?)”);
    //设置参数
    st.setObject(1,” CLIENT==\”PWQ\” || SELLERID.STATE==e\”California\”");
    //执行esProc存储过程
    ResultSet set =st.executeQuery();