Как правильно использовать узел.модуль на 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 ответов:
Я автор книги 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()