hillpig的个人博客分享 http://blog.sciencenet.cn/u/hillpig 畅想ing,思考ing,前行ing Email:bluevaley@gmail.com

博文

Node.js如何方便的使用PostgreSQL中的JSONB数据(PG JSON系列6)

已有 7078 次阅读 2016-10-19 09:12 |个人分类:postgresql|系统分类:科研笔记| PostgreSQL, JSONB

前5篇博文,分别写了使用PG的JSONB类型的几个方面:

  1. 使用PostgreSQL中的row_to_json()直接获得JSON(PG JSON系列1)

  2. JSON/JSONB如何做增删改查(PG JSON系列2)

  3. 组合使用PostgreSQL的ARRAY和JSONB数据类型(PG JSON系列3)

  4. PG中验证JSON Schema(PG JSON系列4)

  5. PG中JSONB存储和访问效率(PG JSON系列5)

这一篇写写Node.js如何方便的使用PostgreSQL中的JSONB数据,为什么要写Node.js呢(可能很多人还没使用过),这是有原因的,我们先来看Josh Berkus(他是谁?https://www.postgresql.org/community/contributors/ ,第1个人 )写的一篇博文, Why HStore2/jsonb is the most important patch of 9.4 :

Open source databases rise and fall on the popularity of the programming languages which use those databases. ...

While the future is unpredictable, the current momentum in programming languages is behind two platforms: Node.js and Go.  PostgreSQL already enjoys good support and adoption among Go users.  However, our adoption in the Node.js community is less encouraging.

I was given a set of statistics I'm not allowed to publish, but I can summarize them.  Two of them are fairly alarming:

  • PostgreSQL is the database for fewer than 1 out of 8 Node.js deployments which use a database.

  • The rise in popularity of MongoDB almost exactly parallels the rise in usage of Node.js.

If you've watched database adoption trends for the last 20 years like I have, this is alarming.  We are in danger of being sidelined....

What do Node.js users want that we don't have?  There's three main things that I've been able to identify:

  1. A better, faster, driver which fully supports asynchronous querying.

  2. Relatively painless multi-node scaling

  3. Full, indexed support for jsonish hierarchical data and queries.

这里摘录了大片的原文,因为写到很到位,几乎没有废话(Leader都是这样的吗?),一看乔什小伙子就很有商业头脑(价值思维+竞争者思维),总而言之,一句话,适者生存,PG也是世界中的一员,也要寻求生存空间。

那 Node.js 究竟是什么?请看看这里:http://www.ibm.com/developerworks/cn/opensource/os-nodejs/index.html?ca=drs#ibm-pcon  。这里摘录一句话:

它对什么有好处?

正如您此前所看到的,Node 非常适合以下情况:在响应客户端之前,您预计可能有很高的流量,但所需的服务器端逻辑和处理不一定很多。Node 表现出众的典型示例包括:

RESTful API

提供 RESTful API 的 Web 服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合 Node 的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。

其实,我觉得最重要的理由是,现在客户端PC Web+APP+微信编程都用H5(css3/js/ionic/jquery/websocket/framework7/react/bootstrap),服务端编程为何不也用H5里的js呢,反正开发语言都熟悉,干嘛用JAVA? 而且最最重要的是RESTful API的风格并不要求服务端编程花费大量的精力呀,大都是增删改查数据库,没有以往2B业务复杂的中间层业务逻辑,一学就会,干嘛去看别人脸色学习复杂的J2EE/PHP/.NET。而且老板也喜欢呀,一个前端程序员搞定前端、Node.js、数据库,多省钱,以前至少是2倍或3倍以上的成本呀。

我一定要把上面的字体加黑变红,才显得这段话是多么重要,你甭管Node.js一大堆的劣势,时代变了,2c业务+js包打天下+RESTful API三大宇宙最强好声音(别只看 中国好声音),于是乎Node.js也就这么火起来了,http://www.google.cn/trends/explore#q=%2Fm%2F0bbxf89%2C%20json&cmpt=q&tz=Etc%2FGMT-8看下图:


Node.js和JSON几乎是从2009年以后就携手同行了,所以,我们还是要写写 Node.js+JSON+PostgreSQL 三兄弟的量子纠缠态。

开发环境:

1. Node.js入门,如何写Restful API

Manuel(http://manuel.manuel.net/)写的http://www.nodebeginner.org/index-zh-cn.html 简直就是经典(我学习的榜样),花1个小时了解Node.js入门。

然后再花1个小时看看 Designing a RESTful API With Node and Postgres 如何用Node.js+PostgreSQL实现Restful API(下一节我们将使用这个例子)。

或者再看看: http://mherman.org/blog/2015/02/12/postgresql-and-nodejs/#.WA1oYfl96Uk

2. Node.js如何使用PG的JSONB

我们使用上面 Designing a RESTful API With Node and Postgres 里面的例子( Node.js, express-generator, pg-promise , PostgreSQL v9.6, and Bluebird),然后使用PG中JSONB存储和访问效率(PG JSON系列5)中的第2类表做实验(第1类表类似):

-- Table: R_PIC_PERSON_JSONB_USEARRAY

-- 照片中的人的信息表,用JSONB实现,JSONB数组形式,即一行对应普通表的多行

DROP TABLE IF EXISTS R_PIC_PERSON_JSONB_USEARRAY CASCADE;

CREATE TABLE R_PIC_PERSON_JSONB_USEARRAY (

id serial,-- 照片id

persons jsonb NOT NULL -- 格式为:[{"position":"前1排左1","name":"张晓陆","phone":"18910180100","city":"济南","organization":"中科院计算所","attendanceYear":2012,"graduationYear":2016},{"position":"前1排左2","name":"张晓陆","phone":"18910180100","organization":"中科院计算所","attendanceYear":2012,"graduationYear":2016}]

)WITH (OIDS=FALSE);

测试数据:

insert into R_PIC_PERSON_JSONB_USEARRAY values

(1,

'[{"position":"前1排左1","name":"张晓陆","phone":"18910180100","city":"济南","organization":"中科院计算所","attendanceYear":2012,"graduationYear":2016},

{"position":"前1排左2","name":"张晓陆2","phone":"18910180100","organization":"中科院计算所","attendanceYear":2012,"graduationYear":2016}]'

);

好,我们来设计如下RESTful API:

URLHTTP       Verb       Action

/api/pic/persons    GET      返回该图片中的所有人,需要传入参数:图片的id

/api/pic/person/:idx  GET        返回图片中第idx个人

/api/pic/persons    POST        增加一个人

/api/pic/person/:idx   PUT        更新一个人

/api/pic/person/:idx   DELETE      删除一个人

然后在index.js里增加路由:

router.get('/api/pic/persons', db.getPicAllPersons);

router.get('/api/pic/person/:idx', db.getPicSinglePerson);

router.post('/api/pic/persons', db.createPicPerson);

router.put('/api/pic/person/:idx', db.updatePicPerson);

router.delete('/api/pic/person/:idx', db.removePicPerson);

在queries.js里增加处理函数:

function getPicAllPersons(req, res, next) {

 var picID = parseInt(req.query.id);

 db.one('select * from R_PIC_PERSON_JSONB_USEARRAY where id = $1', picID)

   .then(function (data) {

     res.status(200)

       .json({

         status: 'success',

         data: data,

         message: 'Retrieved ALL persons in a pic'

       });

   })

   .catch(function (err) {

     return next(err);

   });

}

上面的req.query.id是指图片的id,用Postman测试结果如下:


然后,

function getPicSinglePerson(req, res, next) {

var personIdx = parseInt(req.params.idx);

var picID = parseInt(req.query.id);

 db.one('select a.id,a.persons->$1 as person from R_PIC_PERSON_JSONB_USEARRAY a  where a.id = $2', [personIdx,picID])

   .then(function (data) {

     res.status(200)

       .json({

         status: 'success',

         data: data,

         message: 'Retrieved ONE PERSON'

       });

   })

   .catch(function (err) {

     return next(err);

   });

}

通过http://localhost:3000/api/pic/person/1?id=1 测试一下, 返回结果为:

{"status":"success","data":{"id":1,"person":{"name":"张晓陆2","phone":"18910180100","position":"前1排左2","organization":"中科院计算所","attendanceYear":2012,"graduationYear":2016}},"message":"Retrieved ONE PERSON"}

然后是 router.post('/api/pic/persons', db.createPicPerson); 的处理函数

function createPicPerson(req, res, next) {

var aPersonJson = req.body;

var picID = parseInt(req.query.id);

 db.none('update R_PIC_PERSON_JSONB_USEARRAY set persons = persons || $1  where  id =  $2',[aPersonJson,picID])

   .then(function () {

     res.status(200)

       .json({

         status: 'success',

         message: 'Inserted one person'

       });

   })

   .catch(function (err) {

     return next(err);

   });

}

用Postman测试结果如下:


剩下的

router.put('/api/pic/person/:idx', db.updatePicPerson);

router.delete('/api/pic/person/:idx', db.removePicPerson);

我就不写了,大家当作练习吧。

结论:在Node.js里结合express-generator, pg-promise访问pg的JSONB类型和普通的访问数据库没什么异同,当然好处是直接可以把客户端POST传入的json对象灌入到PG中,以及从PG中直接返回JSON串,而在Node.js层面只是做简单的封装转发


参考:

  1. Why HStore2/jsonb is the most important patch of 9.4, http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html  

  2. http://blog.j0.hn/post/48591247017/using-json-in-postgres-and-nodejs

  3. http://www.ibm.com/developerworks/cn/opensource/os-nodejs/index.html?ca=drs#ibm-pcon  

  4. http://www.nodebeginner.org/index-zh-cn.html

  5. http://martinfowler.com/articles/injection.html

  6. https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4

  7. https://gist.github.com/iksose/9401758

  8. https://blog.risingstack.com/node-js-database-tutorial/

  9. https://medium.com/@jeffandersen/building-a-node-js-rest-api-with-express-46b0901f29b6#.t9s9w02j6

  10. https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

码字码了半天,手指头都麻了,如果觉得对您还有用的话,赞助一下辛苦费吧:






https://blog.sciencenet.cn/blog-419883-1009599.html

上一篇:PG中JSONB存储和访问效率(PG JSON系列5)
下一篇:单点登录系统很好的网站
收藏 IP: 61.135.169.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-5-2 08:35

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部