如何用 esProc 简化 MongoDB 的查询

 

MongoDB 自带的查询语法功能比较繁琐,简单的任务也要写很长代码,复杂计算更难实现,比如:

SPL assists MongoDB: Only keep the running total for the last item in the partition

SPL assists MongoDB: Replace substring in array of objects with nested objects

SPL assists MongoDB: Find multiple latest by filter criteria

esProc 提供了 MongoDB 访问接口,内置强大的计算函数,可以简化 MongoDB 的查询。

下面,我们来尝试一下如何将 esProc 集成到应用中。

先下载并安装 esProc,推荐标准版:https://www.raqsoft.com.cn/download/download-jsq

Picture2png

再下载 esProc 外部库,以访问 mongoDB 等外部数据源,同样从上面地址下载。
将外部库的 zip 文件解压在任意目录,比如 d:\esProcSTD\extlib
启动 esProc IDE,打开菜单 "Tools->Options",找到配置项 "External library directory",导航到刚才的目录。

Picture3png
导航到外部库目录后,会显示出数据源列表,在列表中勾选 MongoCli。

Picture4png

重新启动 IDE,新建脚本,编写下面的代码,加载例子 1 的数据:


 A
1 =mongo_open("mongodb://127.0.0.1:27017/local")
2 =mongo_shell@d(A1, "{'find':'grp_score','projection':{'_id':0}}")
3 =mongo_close(A1)

按 ctrl-F9 执行,可以在 IDE 右边看到 A2 的执行结果,以数据表的形式呈现,这对调试 SPL 代码很方便。

Picture5png

从 MongoDB 简单加载数据后,就可以用 SPL 简化复杂的 MongoDB 的查询了。第 1 个例子的完整代码是:


 A
1 =mongo_open("mongodb://127.0.0.1:27017/local")
2 =mongo_shell@d(A1, "{'find':'grp_score','projection':{'_id':0}}")
3 =mongo_close(A1)
4 =A2.select(seq>=arg1 && seq<=arg2)
5 =A4.group(grp;(a=~.sort(seq),a.m(-1).x=a.sum(score)))
6 =json(A4)

先通过参数过滤数据,再将汇总值写在本组最后一条记录上。运行后可以看到结果:

Picture6png

把上面脚本保存在某个目录中,比如 D:\data\grp_score.splx,后续 Java 代码会用到。

上面例子 1 是单层数据,下面例子 2 是多层数据:


 A
1 =mongo_open("mongodb://127.0.0.1:27017/local")
2 =mongo_shell@d(A1, "{'find':'meetings','projection':{'_id':0}}")
3 =mongo_close(A1)
4 =A2.run(organizer.run(avatar="https://new.com/"+mid(avatar,17)), meetings.run(owner.run(avatar="https://new.com/"+mid(avatar,17)), participants.run(avatar="https://new.com/"+mid(avatar,17)) ) )

在 IDE 右边可以逐层展开并观察多层数据,其中 A2 的结构如下:

Picture7png

类似地,把上面脚本保存在目录中,比如 D:\data\meetings.splx。

在 IDE 中调试通过后,下面配置 Java 应用环境。
从目录 "[安装目录]\esProc\lib" 下找到 esProc JDBC 相关的 jar 包:esproc-bin-xxxx.jar、icu4j_60.3.jar。

Picture8png
将这两个 jar 包部署到 Java 开发环境的类路径下。外部库的 jar 包会通过配置文件动态加载,不需要手工部署。
再从目录 "[安装目录]\esProc\config" 下找到 esProc 配置文件 raqsoftConfig.xml,同样部署到 Java 开发环境的类路径下。

Picture9png
比较重要的配置项有两处:mainPath,这是脚本等文件的默认路径;importLibs->lib,这是已经启用的外部库。可以在配置文件里手工修改,也可以通过 IDE 里的配置界面修改。
接下来,就可以编写 Java 代码,通过 esProc JDBC 执行 SPL 了,先试试例子 1:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection con= DriverManager.getConnection("jdbc:esproc:local://");
PreparedStatement st = con.prepareCall("call grp_score(?,?)");
st.setInt(1,1);
st.setInt(2,4);
ResultSet rs = st.executeQuery();

运行后可以看到结果:

Picture10png
可以看到,esProc JDBC 调用 SPL 脚本过程和数据库 JDBC 调用存储过程一样。

例子 2 类似,在 Java 中用文件名调用 SPL 脚本:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection con= DriverManager.getConnection("jdbc:esproc:local://");
PreparedStatement st = con.prepareCall("call meetings()");
ResultSet rs = st.executeQuery();

执行结果像下面这样:

Picture11png

esProc 还支持简单 SQL,方便数据库程序员使用。比如加载例子 1 的数据,再执行 SQL,脚本可以这样写:


 A
1 =mongo_open("mongodb://127.0.0.1:27017/local")
2 =mongo_shell@d(A1, "{'find':'grp_score','projection':{'_id':0}}")
3 =mongo_close(A1)
4 $select case grp when 'A' then 'Class 1' when 'B' then 'Class 2' else 'others' end level,sum(score) as subtotal from {A2} where seq>=? and seq<=? group by grp ;arg1,arg2
5 return A4

将脚本文件存为 grp_scoreSQL.splx,执行后结果如下:

Picture12png
esProc 官网上还有很多简化 MongoDB 查询的例子,感兴趣的可以看看。