नोड .js postgresql मॉड्यूल का उपयोग करने का उचित तरीका क्या है?


95

मैं Heroku पर एक नोड.जेएस एप्लिकेशन लिख रहा हूं और पीजी मॉड्यूल का उपयोग कर रहा हूं । मैं डेटाबेस को क्वेरी करने के लिए आवश्यक प्रत्येक अनुरोध के लिए क्लाइंट ऑब्जेक्ट प्राप्त करने के लिए "सही" तरीके का पता नहीं लगा सकता।

प्रलेखन इस तरह कोड का उपयोग करता है:

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

मैं दूसरे विकल्प की ओर झुक रहा हूं क्योंकि मेरा मानना ​​है कि हरोकू के लिए मुफ्त डेटाबेस उदाहरण वैसे भी एक कनेक्शन तक सीमित है, लेकिन क्या इस तरह से करने में कोई कमियां हैं? क्या मुझे यह जांचने की आवश्यकता है कि क्या उपयोग करने से पहले मेरा क्लाइंट ऑब्जेक्ट अभी भी हर बार जुड़ा हुआ है?

जवाबों:


158

मैं नोड-पोस्टग्रेज का लेखक हूं । सबसे पहले, मैं माफी माँगता हूँ कि दस्तावेज सही विकल्प को स्पष्ट करने में विफल रहा है: यह मेरी गलती है। मैं इसे सुधारने की कोशिश करूंगा। मैंने इसे समझाने के लिए अभी एक जिस्ट लिखा क्योंकि ट्विटर पर बातचीत बहुत लंबी हो गई।

का उपयोग करना pg.connectहै जाने का रास्ता एक वेब वातावरण में।

PostgreSQL सर्वर प्रति कनेक्शन एक समय में केवल 1 क्वेरी को संभाल सकता है। इसका मतलब है कि यदि आपके पास new pg.Client()अपने बैकएंड से 1 वैश्विक जुड़ा हुआ है, तो आपका पूरा ऐप बोतकनेक्क्ड है, जो इस बात पर आधारित है कि प्रश्नों का जवाब देने के लिए कितनी तेजी से पोस्टग्रैट्स हो सकते हैं। यह शाब्दिक रूप से प्रत्येक प्रश्न को पंक्तिबद्ध करते हुए, सब कुछ को पंक्तिबद्ध करेगा। हाँ, यह async है और इसलिए यह ठीक है ... लेकिन क्या आप अपने थ्रूपुट को 10x से गुणा नहीं करेंगे? किसी चीज़ 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को ग्राहकों के कस्टम पूल से या जो कुछ भी हो सकते हैं और केवल एक ही स्थान पर चीजों को बदलना होगा।

नोड-पीजी-क्वेरी मॉड्यूल पर एक नज़र डालें जो ऐसा करता है।


2
क्षमा करें, मैं DBMS के लिए काफी नया हूं और मुझे अभी भी इसे समझने में समस्या है, लेकिन हम "कूड़े pg.connect" कॉल क्यों नहीं करना चाहते हैं? क्या यह सादगी के लिए है या प्रदर्शन के कारण है? उदाहरण के लिए, मैं अपने मूल ऐप में सभी मार्गों में से एक में एक बार pg.connect को कॉल करता हूं (सभी एक ही conString के साथ)। यह ठीक है? सहज रूप से, ऐसा लगता है कि जब भी मैं इसे कॉल करता हूं (जो मैं नहीं चाहता), तो यह उसी db के लिए एक नया कनेक्शन बना रहा है, लेकिन क्या यह आंतरिक रूप से पूल किए गए कनेक्शन का उपयोग करता है? धन्यवाद।
user1164937

बहुत बढ़िया। आप प्रति अनुरोध एक के बजाय प्रति कनेक्शन एक कनेक्शन क्यों नियोजित कर रहे हैं? मैं एक अनुरोध के भीतर कई प्रश्नों में एक कनेक्शन साझा करने के लिए एक उपयुक्त तरीके की तलाश कर रहा हूं और यहां आपका उत्तर खोजने से पहले res.locals पर विचार कर रहा था।
जो लैप

2
अरे रुको। ऐसा लगता है कि आपका समाधान यहां लेनदेन का समर्थन नहीं करेगा।
जो लैप

यह गिथब को दिया जाना चाहिए।
रयान विलिस

1
ध्यान दें कि नोड- postgres उर्फ ​​पीजी के पोस्ट v7 को हटा दिया गया था। देखें stackoverflow.com/questions/45174120/pg-connect-not-a-function
कॉलिन डी

23

मैं पृष्ठ-प्रतिज्ञा का लेखक हूं , जो वादों के माध्यम से नोड-पोस्टग्रेज के उपयोग को सरल करता है।

यह डेटाबेस से कनेक्ट करने और डिस्कनेक्ट करने के सही तरीके के बारे में मुद्दों को संबोधित करता है, नोड-पोस्टग्रेज द्वारा लागू कनेक्शन पूल का उपयोग करके , अन्य चीजों के साथ, जैसे स्वचालित लेनदेन।

पीजी-वादे में एक व्यक्तिगत अनुरोध सिर्फ आपके व्यवसाय तर्क के लिए प्रासंगिक है

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;

आप उदाहरण ट्यूटोरियल द्वारा , या प्रोजेक्ट के होम पेज पर कई और उदाहरण पा सकते हैं ।


नमस्ते, हरोकू केवल एसएसएल कनेक्शन स्वीकार करता है। इसमें pgद्वारा निर्दिष्ट किया गया है pg.defaults.ssl = true;। आप इसमें कैसे करते हैं pg-promise?
ओकराम

@ocram github.com/vitaly-t/pg-promise/wiki/… , या आप कनेक्शन मापदंडों के भीतर SSL निर्दिष्ट कर सकते हैं: github.com/vitaly-t/pg-promise/wiki/Connection
-Syntax

मैं इसमें से अधिकांश के लिए नया हूं: जावास्क्रिप्ट, वादे, पोस्टग्रेट्स, आदि और यह वही है जो मुझे चाहिए था। धन्यवाद!!
रयान रोडेमॉयर

1
मैं तो बस ऐसा करने से यह काम कर रहे हो गया @ocrampgp.pg.defaults.ssl = true;
CharlieC

जब हम पोस्टग्रेज के लिए कई क्वेरी अनुरोध देते हैं तो क्या यह स्वचालित रूप से पोस्टग्रुप थ्रूपुट को बेहतर बनाने के लिए कई कनेक्शन बनाएगा?
सूंदर

5

पूल अब जाने का रास्ता है। कुछ इस तरह

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


1

विश्व स्तर पर एक पीजी पूल बनाना बेहतर होता है और हर बार आपको एक डीबी ऑपरेशन क्लाइंट का उपयोग करने की आवश्यकता होती है और फिर इसे वापस पूल में जारी करना होता है। एक बार सभी डीबी संचालन का उपयोग कर पूल को समाप्त कर दिया जाता है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();

        });
}

});  

अधिक जानकारी के लिए, आप मेरे ब्लॉग पोस्ट - स्रोत का उल्लेख कर सकते हैं


0

जैसा कि आप दस्तावेज़ीकरण से देख सकते हैं कि दोनों विकल्प मान्य हैं, इसलिए आप जो भी पसंद करते हैं उसे चुनें। आप के रूप में, मैं दूसरी पसंद के साथ जाऊंगा।


जब कनेक्शन गिर जाता है तो फिर से कनेक्ट करने के बारे में क्या? क्या यह अपने आप हो गया है? त्रुटि से निपटने पर विकी पेज है ... खाली github.com/brianc/node-postgres/wiki/Error-handling
alltom

मैंने इसे अलग से पूछा है: stackoverflow.com/questions/15619456/…
alltom

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

यह कनेक्शन को पूल में वापस भी नहीं भेजता है। यह पूल को तेजी से असली बना देगा। node-postgresपेज पर मूल उदाहरण इससे बेहतर है।
13:55 बजे महत्वपूर्ण-टी

-2

यहां बताया गया है कि मैं इसे कैसे करता हूं, "उपरोक्त दृष्टिकोण के सभी"

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

1
तो आप कोई कनेक्शन प्रबंधन, कोई लेनदेन समर्थन और कोई कार्य समर्थन के साथ समाप्त हो जाएगा। फिर क्या है?
महत्वपूर्ण-

1
वह कौन सी भाषा है? कॉफ़ी? berk
काब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.