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

Javascript 使用node.js postgresql模块的正确方法是什么?,javascript,postgresql,node.js,heroku,Javascript,Postgresql,Node.js,Heroku,我正在Heroku上编写node.js应用程序,并使用。我无法找到一种“正确”的方法来为查询数据库所需的每个请求获取客户机对象 文档使用如下代码: pg.connect(conString, function(err, client) { // Use the client to do things here }); module.exports = { query: function(text, values, cb) { pg.connect(function(err

我正在Heroku上编写node.js应用程序,并使用。我无法找到一种“正确”的方法来为查询数据库所需的每个请求获取客户机对象

文档使用如下代码:

pg.connect(conString, function(err, client) {
  // Use the client to do things here
});
module.exports = {
   query: function(text, values, cb) {
      pg.connect(function(err, client, done) {
        client.query(text, values, function(err, result) {
          done();
          cb(err, result);
        })
      });
   }
}
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;
但是您肯定不需要在每个使用数据库的函数中调用
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的免费数据库实例无论如何只限于一个连接,但是这样做有什么缺点吗?每次使用客户端对象之前,是否需要检查它是否仍处于连接状态?

您可以从两个选项中看到,这两个选项都有效,因此选择您喜欢的选项。和你一样,我会选择第二种选择。

我是这本书的作者。首先,我很抱歉文档没有明确正确的选项:这是我的错。我会努力改进的。我刚才写信解释这一点,因为Twitter的时间太长了

在web环境中,使用
pg.connect
是一种方法

PostgreSQL server每次只能处理一个查询。 这意味着如果您有一个全局
新的pg.Client()
连接到您的 后端根据postgres的速度对整个应用程序进行瓶颈检查 可以回答查询。它会把所有东西排成一行,排队 每个查询。是的,它是异步的,所以这没关系……但是你不会吗 而是将吞吐量乘以10倍?使用
pg.connect
设置
pg.defaults.poolSize
到合理的程度(我们做25-100,不确定 正确的数字)

new pg.Client
适用于您知道自己在做什么的情况。当你需要的时候 由于某种原因或需要非常谨慎地处理一个长期存在的客户 控制生命周期。一个很好的例子是使用
监听/通知
。倾听的客户需要在身边并且 已连接且未共享,因此它可以正确处理
NOTIFY
消息。 另一个例子是当打开一个一次性客户机杀死一些人时 挂起的东西或在命令行脚本中

一个非常有用的方法是将应用程序中对数据库的所有访问集中到一个文件中。不要乱丢
pg.connect
电话或新客户端。有一个类似于
db.js
的文件,看起来像这样:

pg.connect(conString, function(err, client) {
  // Use the client to do things here
});
module.exports = {
   query: function(text, values, cb) {
      pg.connect(function(err, client, done) {
        client.query(text, values, function(err, result) {
          done();
          cb(err, result);
        })
      });
   }
}
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;
通过这种方式,您可以将实现从
pg.connect
更改为客户机自定义池或其他任何内容,只需在一个地方进行更改

看一看就可以做到这一点。

我是的作者,它简化了via承诺的使用

它解决了有关连接数据库和断开与数据库连接的正确方式的问题,使用由自动化事务等实现的连接池

中的单个请求归结为与您的业务逻辑相关的内容:

db.any('SELECT * FROM users WHERE status = $1', ['active'])
    .then(data => {
        console.log('DATA:', data);
    })
    .catch(error => {
        console.log('ERROR:', error);
    });
i、 e.在执行查询时,您不需要处理连接逻辑,因为您只在全局设置了一次连接,如下所示:

pg.connect(conString, function(err, client) {
  // Use the client to do things here
});
module.exports = {
   query: function(text, values, cb) {
      pg.connect(function(err, client, done) {
        client.query(text, values, function(err, result) {
          done();
          cb(err, result);
        })
      });
   }
}
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;

您可以在教程或上找到更多的示例。

以下是我的做法,类似于“上述所有方法”


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

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

最好全局创建一个pg池,每次需要执行db操作时,使用客户机,然后将其释放回池中。完成所有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();

        });
}

});  

有关更多详细信息,您可以参考我的博客帖子-

现在就去游泳池

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('当连接断开时重新连接怎么样?这是自动完成的吗?关于错误处理的wiki页面是空的…我已经单独问过了:对不起,我对DBMS相当陌生,我在理解这一点上仍然有问题,但是为什么我们不想“丢弃pg.connect”调用?是为了简单还是出于性能原因?例如,我在我的基本应用程序中的每个路由中调用pg.connect一次(所有路由都具有相同的构造)。这可以吗?直觉上,每当我调用它时,它都会感觉到它正在与同一个db建立新的连接(我不想要),但它是否在内部使用池连接?谢谢。太棒了。为什么您在每个查询中使用一个连接,而不是在每个请求中使用一个连接?我一直在寻找一种合适的方法来在一个请求中跨多个查询共享一个连接,并且在找到您的答案之前一直在考虑res.locals。哦,等等,它看起来像您的解决方案此处不支持事务。如何关闭pg连接?请注意,pg.connect在节点postgres aka pg的v7后被删除。请参阅,这样您将最终没有连接管理、事务支持和任务支持。这有什么意义?这是什么语言?咖啡?berkHi,Heroku只接受SSL连接。在
pg
t中his由
pg.defaults.ssl=true;
指定。您如何在
pg promise
中执行此操作?@ocram,或者您可以在连接参数中指定ssl:我对大多数内容都是新手:javascript、promises、postgres等。这正是我所需要的。谢谢!!@ocram我刚刚通过
pgp.pg.defaults.ssl=tru完成此工作e、 
当我们向postgres发出多个查询请求时,这会创建多个连接以自动提高postgres吞吐量吗?这甚至不会释放回池的连接。它会很快耗尽池。节点postgres
页面上的基本示例比这做得更好。