使用nodered操作数据库
缘起
node-red是目前为止我用到的最好的物联网开发工具,它既可以将相关经验沉淀为节点,又可以灵活快速的定制开发,快速的满足用户的奇葩需求。美中不足的是,它是用node写的,在数据处理、库的丰富性上不及Java、Python。
这么好的产品,可惜中文资料太少,2019年下半年我会把node-red手册翻译出来,并写一个系列的文章,请大家监督。
先写数据库这一篇,就是发现node-red的文档,特别是结点模块的文档太少了,这导致一个简单的东西,摸熟需要大半天,有文档一个小时就能搞定。
MySQL、SQLServer、Oracle是最常用到的三种数据库,下面我们就以这三种数据库为例,讲讲怎么用node-red操作数据库。
操作MySQL 与 SQLServer
在node-red仓库中,目前操作MySQL 有三种节点, node-red-node-mysql、node-red-contrib-sqldbs、node-red-contrib-odbc。前两种用法差不多,但node-red-contrib-sqldbs支持 Mysql、MSsql、Postgresql、SQLLite四种数据库。安装这个节点可以搞定四种数据库,大家应该都会选它吧。
配置节点
- 创建一个sqldbs节点
在左侧的palette中,搜索sql就可以看到相关节点,往右侧一拖,我们就得到了一个sqldbs节点。 - 配置sqldbs节点
双击sqldbs节点进入配置界面,先编辑数据库,创建一个数据库连接,里面填写的内容无非是IP、端口、用户名、密码、数据库名。这里需要注意的是在Dialect一行需要选择数据库类型,Mysql、MSsql、Postgresql、SQLLite 的填写内容并没有区别。
配置数据库操作类型,这个动作有点多余,从SQL语句可以解析出SQL操作类型,node-red-node-mysql不需要做这个配置。
导入SQL语句
sqldbs节点会从msg.topic这个变量中拿SQL,但是其它节点的输出通常是放在msq.payload中(比如MQTT节点、Inject节点),从Inject 节点到sqldbs节点,中间需要一个转换节点,我用了一个function节点。
在Inject 节点中,我注入了一个Json串,该串中包含了我要写入的信息,这也能模拟我从其它节点拿到数据的格式。
{ "name": "longtt", "age": 21, "class_name": "401" }
在function节点中,我把json串的信息组装到了SQL语句中,并替换了msg
var insertOneStudent="INSERT INTO student(name, age, class_name) VALUES ('%s', %d, '%s')"; var newMsg = { "topic": util.format(insertOneStudent, msg.payload.name, msg.payload.age, msg.payload.class_name) } return newMsg;
执行
点击注入节点按钮,会触发注入操作,在右侧的调试信息窗口,我们可以看到调试信息。去数据库查询,我们可以看到相关数据记录已经成功创建。
操作Oracle
Oracle 数据库操作有两个难点,一个是安装麻烦,一个是节点文档非常少。
安装Oracle操作节点
在node-red节点仓库中,有两个节点 node-red-contrib-oracledb、node-red-contrib-oracledb-mod, node-red-contrib-oracledb已经过时了,节点安装失败。所以我把精力放到节点 node-red-contrib-oracledb-mod 上,但是也遇到了种种问题。
无法定位到Oracle Client 库
配置好OracleDB的连接配置后,OracleDB节点会去建数据库连接,这个过程失败了。Oracle-server error connection to 119.3.59.75:1521/orcl: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help Node-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html You must have 64-bit Oracle client libraries in LD_LIBRARY_PATH, or configured with ldconfig. If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html
这和Oracle的律师有很大关系,我用过的数据库工具都需要单独安装从Oracle官网下载的instantclient,node-red也不例外。
于是我就到Oracle官网下载了一个instantclient(具体版本取决于你的操作系统版本),然后在我的.bashrc中添加了以下几条配置(注意路径是我机器的路径)。重启了一下node-red,之后OracleDB节点连接就成功了。export LD_LIBRARY_PATH=/root/instantclient_19_3:$LD_LIBRARY_PATH export OCI_LIB_DIR=/root/oracle/instantclient_19_3 export OCI_INC_DIR=/root/oracle/instantclient_19_3/sdk/include
- 配置oracle-db
必须批评一下,oracle-db与数据库的连接配置中没有区分 sid、service-name两种模式,我的数据库用的是service-name这种模式,sid这种模式我没有试验。SQL query、Field mappings 两个配置Tab页面,把我绕得很辛苦,花了一天,很多尝试都失败了,我建议大家不要配置这两页。
导入SQL语句
与sqldbs 不同的是,oracle-db的SQL语句用的是msg.query,并且支持利用占位符从msg.payload中组装数据。我仍然使用Inject节点传入Json串,使用function节点进行数据组合。
Inject节点的写法参上,在fuction节点中我导入了query,并替换了payload。
var insertOneStudent="INSERT INTO student(id, name, age, class_name) VALUES (:myid, :myname, :myage, :myclassname)"; var newMsg = { "query": insertOneStudent, "payload": [msg.payload.id, msg.payload.name, msg.payload.age, msg.payload.class_name] } return newMsg;
执行
我写了一个Select查询语句,点击注入节点按钮,会触发注入操作,在右侧的调试信息窗口,我们可以看到查询到的信息。
var SelectOneStudent="select * from student where name =:myname"; var newMsg = { "query": SelectOneStudent, "payload": [msg.payload.name] } return newMsg;
the ending
node-red 是一款让我惊艳的工具,后面我会继续深入研究下去,写一些更有深度的文章,需要交流的同学请在下面留言。