什么是使用node.js postgresql模块的正确方法?
我正在Heroku上编写node.js应用程序,并使用pg模块 。 我找不到“正确”的方式来获取我需要查询数据库的每个请求的客户端对象。
文档使用这样的代码:
pg.connect(conString, function(err, client) { // Use the client to do things here });
但是当然你不需要在每个使用数据库的函数中调用pg.connect
? 我见过这样的其他代码 :
var conString = process.env.DATABASE_URL || "tcp://postgres:1234@localhost/postgres"; var client = new pg.Client(conString); client.connect(); // client is a global so you can use it anywhere now
我倾向于第二个选项,因为我相信Heroku的免费数据库实例无论如何都只限于一个连接,但是这样做有什么缺点吗? 在使用之前,我是否需要检查每个客户端对象是否仍然连接?
我是node-postgres的作者。 首先,我很抱歉,文件没有做出正确的选项:这是我的错。 我会尽力改善它。 我刚才写了一个Gist来解释这个,因为Twitter 的谈话时间太长了。
使用
pg.connect
是在Web环境中进行的方式。PostgreSQL服务器每个连接一次只能处理1个查询。 这意味着,如果你有1个全局
new pg.Client()
连接到你的后端,你的整个应用程序是基于postgres可以响应查询的速度的瓶颈。 它从字面上将所有行排队,每个查询排队。 是的,这是asynchronous的,所以这是没问题的,但是你不是把你的吞吐量乘以10倍吗? 使用pg.connect
将pg.connect
设置为理智的(我们做25-100,不确定正确的数字)。
new pg.Client
是当你知道你在做什么。 当你需要一个长期居住的客户出于某种原因,或需要非常小心地控制生命周期。 一个很好的例子是使用LISTEN/NOTIFY
。 监听客户端需要在周围并连接,而不是共享,因此它可以正确处理NOTIFY
消息。 其他的例子是打开一个1-off客户端来杀死一些挂起的东西或命令行脚本。
一个非常有用的事情是将您应用程序中对数据库的所有访问集中到一个文件中。 不要乱扔pg.connect
电话或新的客户端。 有一个像db.js
这样的文件:
module.exports = { query: function(text, values, cb) { pg.connect(function(err, client, done) { client.query(text, values, function(err, result) { done(); cb(err, result); }) }); } }
通过这种方式,您可以将您的实现从pg.connect
更改为自定义的客户端池或其他任何东西,只需要在一个地方进行更改。
看看这样做的node-pg-query模块 。
我是pg-promise的作者,它通过承诺简化了对node-postgres的使用。
它解决了连接到数据库和从数据库断开连接的正确方法的问题,使用由node-postgres实现的连接池,以及诸如自动化事务等。
pg-promise中的个别请求归结为与您的业务逻辑相关的内容:
db.any('SELECT * FROM users WHERE status = $1', ['active']) .then(data => { console.log('DATA:', data); }) .catch(error => { console.log('ERROR:', error); });
即在执行查询时,不需要处理连接逻辑,因为您只在全局设置连接一次,如下所示:
const pgp = require('pg-promise')(/*options*/); const cn = { host: 'localhost', // server name or IP address; port: 5432, database: 'myDatabase', user: 'myUser', password: 'myPassword' }; // alternative: // const cn = 'postgres://username:password@host:port/database'; const db = pgp(cn); // database instance;
您可以在“ 按示例学习”教程或在项目主页上find更多示例。
正如你从文档中看到的,这两个选项都是有效的,所以select你喜欢的。 和你一样,我会select第二个select。
我感兴趣的是一个非常简单的处理程序,所以我做了我自己的而不是复杂的。 我没有幻想,这是超级基本的,但它可以帮助一些人开始。 基本上,它连接,运行查询,并为您处理错误。
function runQuery(queryString, callback) { // connect to postgres database pg.connect(postgresDatabase.url,function(err,client,done) { // if error, stop here if (err) {console.error(err); done(); callback(); return;} // execute queryString client.query(queryString,function(err,result) { // if error, stop here if (err) {console.error(err+'\nQuery: '+queryString); done(); callback(); return;} // callback to close connection done(); // callback with results callback(result.rows); }); }); }
那么你可以这样调用它:
runQuery("SELECT * FROM table", function(result) { // Whatever you need to do with 'result' }
以下是我如何做到的,有点“上述所有方法”
Promise = require 'bluebird' pg = module.exports = require 'pg' Promise.promisifyAll pg.Client.prototype Promise.promisifyAll pg.Client Promise.promisifyAll pg.Connection.prototype Promise.promisifyAll pg.Connection Promise.promisifyAll pg.Query.prototype Promise.promisifyAll pg.Query Promise.promisifyAll pg connectionString = process.env.DATABASE_URL module.exports.queryAsync = (sql, values) -> pg.connectAsync connectionString .spread (connection, release) -> connection.queryAsync sql, values .then (result) -> console.log result.rows[0] .finally -> release()