使用node.js postgresql模块的正确方法是什么?

时间:2011-12-13 04:38:49

标签: javascript postgresql node.js heroku

我正在Heroku上编写一个node.js应用程序并使用pg module。我无法弄清楚为查询数据库所需的每个请求获取客户端对象的“正确”方法。

文档使用如下代码:

pg.connect(conString, function(err, client) {
  // Use the client to do things here
});

但是你肯定不需要在每个使用数据库的函数中调用pg.connect吗?我见过other code这样做:

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的免费数据库实例无论如何仅限于一个连接,但是这样做有什么缺点吗?在我使用它之前,是否每次都需要检查我的客户端对象是否仍然连接?

7 个答案:

答案 0 :(得分:148)

我是node-postgres的作者。首先,我道歉文档未能使正确的选项明确:这是我的错。我会尝试改进它。我刚刚写了a Gist来解释这一点,因为the conversation对Twitter来说变得太长了。

  

在网络环境中使用pg.connect 的方式

     

PostgreSQL服务器每个连接一次只能处理1个查询。   这意味着如果您有1个全局new pg.Client()连接到您的   后端你的整个应用程序是基于postgres的速度瓶颈   可以回复查询。它确实会排列一切,排队   每个查询。是的,它是异步的,所以没关系...但不是你   而是将您的吞吐量乘以10倍?使用pg.connect设置   pg.defaults.poolSize理智的东西(我们做25-100,不确定   正确的数字)。

     当您知道自己在做什么时,

new pg.Client就是为了。当你需要的时候   一个长寿的客户由于某种原因或需要非常小心   控制生命周期。一个很好的例子就是使用时   LISTEN/NOTIFY。听取客户端需要在和周围   已连接且未共享,因此可以正确处理NOTIFY条消息。   其他的例子就是打开一次性客户端来杀死一些   挂起的东西或命令行脚本。

一个非常有用的功能是将应用程序中对数据库的所有访问权限集中到一个文件中。不要乱丢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 module

答案 1 :(得分:22)

我是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;

您可以在Learn by Example教程或project's home page上找到更多示例。

答案 2 :(得分:1)

游泳池是现在的去处。像这样的东西

const { Pool } = require('pg');

    const pool = new Pool({
      connectionString: DATABASE_URL,
      ssl: false,
      max: 20,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
    });
    module.exports = {
        query: (text, params) => pool.query(text, params)
      }

它可以用作db.query('<BEGIN,COMMIT,ROLLBACK,your query,anything')

答案 3 :(得分:0)

documentation可以看出,这两个选项都有效,因此请根据自己的喜好选择。就像你一样,我会选择第二种选择。

答案 4 :(得分:0)

最好在全局创建pg池,每次需要执行db操作时,请使用客户端,然后将其释放回池中。完成所有数据库操作后,使用pool.end()

结束池

示例代码 -

let pool = new pg.Pool(dbConfig);
pool.connect(function(err, client, done) {

if (err) {
    console.error('Error connecting to pg server' + err.stack);
    callback(err);
} else {
    console.log('Connection established with pg db server');

    client.query("select * from employee", (err, res) => {

            if (err) {
                console.error('Error executing query on pg db' + err.stack);
                callback(err);
            } else {
                console.log('Got query results : ' + res.rows.length);


               async.each(res.rows, function(empRecord) {   
                        console.log(empRecord.name);
                });
            }
            client.release();

        });
}

});  

有关详细信息,请参阅我的博客文章 - Source

答案 5 :(得分:-1)

我对一个非常简单的处理程序感兴趣,所以我自己创造了它而不会让它变得复杂。我并不幻想它超级基本,但它可以帮助一些人开始。基本上,它会连接,运行查询并为您处理错误。

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'
}

答案 6 :(得分:-2)

以下是我的表现方式,以及上述所有方法&#34;

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()