Как правильно использовать узел.модуль на JS в PostgreSQL?


Я пишу узла.js приложение на Heroku и с помощью модуль 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 ограничен одним соединением в любом случае, но есть ли какие-либо недостатки в этом способе? Нужно ли мне проверять, подключен ли мой клиентский объект каждый раз, прежде чем я его использую?

6 81

6 ответов:

Я автор книги node-postgres. Во-первых, я прошу прощения, что документация не смогла сделать правильный вариант ясным: это моя вина. Я постараюсь его улучшить. Я написал суть только сейчас, чтобы объяснить это, потому что разговор вырос слишком долго Для Twitter.

используя pg.connect и путь в веб-среде.

сервер PostgreSQL может обрабатывать только 1 запрос за раз соединение. Это означает, что если у вас есть 1 global new pg.Client() подключен к backend все ваше приложение bottleknecked на основе того, как быстро postgres может отвечать на запросы. Он буквально будет выстраивать все в очередь каждый запрос. Да, это асинхронно, так что все в порядке...но не вы скорее умножьте свою пропускную способность на 10 раз? Используйте pg.connect установить pg.defaults.poolSize к чему-то вменяемому (мы делаем 25-100, не уверен правильный номер пока).

new pg.Client это когда вы знаете, что вы делающий. Когда вам нужно один долгожитель клиент по какой-то причине или нужно очень тщательно контролируйте жизненный цикл. Хорошим примером этого является использование LISTEN/NOTIFY. Слушающий клиент должен быть рядом и подключен и не используется, поэтому он может правильно обрабатывать NOTIFY сообщения. Другим примером может быть открытие 1-го клиента, чтобы убить некоторых висели вещи или в скриптах командной строки.

одна очень полезная вещь для централизованного доступа к базе данных в ваше приложение в один файл. Не мусорить 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 что делает именно это.

Я автор pg-promise, что упрощает использование node-postgres через обещания.

Он решает вопросы о правильном способе подключения и отключения от базы данных, используя пул соединений, реализованный node-postgres, среди прочего, как автоматические транзакции.

индивидуальный запрос в pg-promise сводится к тому, что отношение к вашему бизнесу логика:

db.any('SELECT * FROM users WHERE status = ', ['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;

вы можете найти еще много примеров в учитесь на примере учебник, или на главная страница проекта.

Как вы можете видеть из документация оба варианта действительны, поэтому выберите то, что вы предпочитаете. Как вы, я бы выбрал второй вариант.

лучше создать пул 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();

        });
}

});  

источник

меня интересовал очень простой обработчик для этого, поэтому я сделал свой собственный, не делая его более сложным. Я не питаю иллюзий, что это супер базовый, но это может помочь некоторым людям начать работу. В основном, он подключается, выполняет запросы и обрабатывает ошибки для вас.

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