[javascript] 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 의 저자입니다 . 첫째, 문서가 올바른 옵션을 명확하게하지 못해 죄송합니다. 그게 내 잘못입니다. 나는 그것을 개선하려고 노력할 것입니다. 트위터에 비해 대화 가 너무 길어 졌기 때문에 이것을 설명하기 위해 방금 요점을 썼습니다 .

사용 pg.connect은 웹 환경 으로 이동하는 방법 입니다.

PostgreSQL 서버는 연결 당 한 번에 하나의 쿼리 만 처리 할 수 ​​있습니다. 즉 new pg.Client(), 백엔드에 1 개의 글로벌이 연결되어 있으면 postgres가 쿼리에 응답 할 수있는 속도에 따라 전체 앱에 병목 현상이 발생합니다. 말 그대로 모든 것을 정렬하여 각 쿼리를 대기열에 넣습니다. 예, 비동기이므로 괜찮습니다 …하지만 처리량에 10 배를 곱하지 않겠습니까? pg.connect set the
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 모듈 을 살펴보십시오 .


답변

나는 promise 를 통해 node-postgres 의 사용을 단순화하는 pg-promise 의 저자입니다 .

자동화 된 트랜잭션과 같이 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 자습서 또는 프로젝트의 홈 페이지 에서 더 많은 예제를 찾을 수 있습니다 .


답변

수영장은 이제 갈 길입니다.

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


답변

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

        });
}

});  

자세한 내용은 내 블로그 게시물- 출처를 참조하세요.


답변

문서 에서 알 수 있듯이 두 옵션 모두 유효하므로 원하는 것을 선택하십시오. 당신으로서 나는 두 번째 선택을 할 것입니다.


답변

나는 이것에 대한 매우 간단한 핸들러에 관심이 있었기 때문에 복잡하게 만들지 않고 직접 만들었습니다. 나는 그것이 매우 기본적이라고 착각하지 않지만 일부 사람들이 시작하는 데 도움이 될 수 있습니다. 기본적으로 연결하고 쿼리를 실행하고 오류를 처리합니다.

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