【问题标题】:How to make connection to Postgres via Node.js如何通过 Node.js 连接到 Postgres
【发布时间】:2012-03-01 14:33:57
【问题描述】:

我发现自己正在尝试创建一个 postgres 数据库,所以我安装了 postgres 并使用 initdb /usr/local/pgsql/data 启动了一个服务器,然后我使用 postgres -D /usr/local/pgsql/data 启动了该实例,现在如何通过节点与之交互?例如,connectionstring 将是什么,或者我如何能够找出它是什么。

【问题讨论】:

    标签: postgresql node.js


    【解决方案1】:

    连接字符串

    连接字符串是以下形式的字符串:

    postgres://[user[:password]@][host][:port][/dbname]
    

    [...] 中的部分可以选择包含或排除)

    一些有效连接字符串的例子包括:

    postgres://localhost
    postgres://localhost:5432
    postgres://localhost/mydb
    postgres://user@localhost
    postgres://user:secret_password@localhost
    

    如果您刚刚在本地计算机上启动了数据库,则连接字符串 postgres://localhost 通常会起作用,因为它使用默认端口号、用户名和无密码。如果数据库是使用特定帐户启动的,您可能会发现需要使用postgres://pg@localhostpostgres://postgres@localhost

    如果这些都不起作用,并且您已经安装了 docker,另一个选择是运行 npx @databases/pg-test start。这将在 docker 容器中启动一个 postgres 服务器,然后为您打印出连接字符串。 pg-test 数据库仅用于测试,因此如果您的计算机重新启动,您将丢失所有数据。

    在 node.js 中连接

    您可以使用@databases/pg 连接到数据库并发出查询:

    const createPool = require('@databases/pg');
    const {sql} = require('@databases/pg');
    
    // If you're using TypeScript or Babel, you can swap
    // the two `require` calls for this import statement:
    
    // import createPool, {sql} from '@databases/pg';
    
    // create a "pool" of connections, you can think of this as a single
    // connection, the pool is just used behind the scenes to improve
    // performance
    const db = createPool('postgres://localhost');
    
    // wrap code in an `async` function so we can use `await`
    async function run() {
    
      // we can run sql by tagging it as "sql" and then passing it to db.query
      await db.query(sql`
        CREATE TABLE IF NOT EXISTS beatles (
          name TEXT NOT NULL,
          height INT NOT NULL,
          birthday DATE NOT NULL
        );
      `);
    
      const beatle = {
        name: 'George',
        height: 70,
        birthday: new Date(1946, 02, 14),
      };
    
      // If we need to pass values, we can use ${...} and they will
      // be safely & securely escaped for us
      await db.query(sql`
        INSERT INTO beatles (name, height, birthday)
        VALUES (${beatle.name}, ${beatle.height}, ${beatle.birthday});
      `);
    
      console.log(
        await db.query(sql`SELECT * FROM beatles;`)
      );
    }
    
    run().catch(ex => {
      // It's a good idea to always report errors using
      // `console.error` and set the process.exitCode if
      // you're calling an async function at the top level
      console.error(ex);
      process.exitCode = 1;
    }).then(() => {
      // For this little demonstration, we'll dispose of the
      // connection pool when we're done, so that the process
      // exists. If you're building a web server/backend API
      // you probably never need to call this.
      return db.dispose();
    });
    

    您可以在https://www.atdatabases.org/docs/pg找到更完整的使用 node.js 查询 Postgres 的指南

    【讨论】:

      【解决方案2】:

      现代而简单的方法:pg-promise:

      const pgp = require('pg-promise')(/* initialization options */);
      
      const cn = {
          host: 'localhost', // server name or IP address;
          port: 5432,
          database: 'myDatabase',
          user: 'myUser',
          password: 'myPassword'
      };
      
      // alternative:
      // var cn = 'postgres://username:password@host:port/database';
      
      const db = pgp(cn); // database instance;
      
      // select and return a single user name from id:
      db.one('SELECT name FROM users WHERE id = $1', [123])
          .then(user => {
              console.log(user.name); // print user name;
          })
          .catch(error => {
              console.log(error); // print the error;
          });
      
      // alternative - new ES7 syntax with 'await':
      // await db.one('SELECT name FROM users WHERE id = $1', [123]);
      

      另请参阅:How to correctly declare your database module

      【讨论】:

      • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
      • 在一个理想的世界里——是的,然而,正如你在上面看到的,这里接受的答案——也只是链接。和那里一样,从链接提供的信息中做一个摘要就太多了,而且考虑到这两个链接都提供给 GitHub 的公共存储库,它们死掉的机会不超过 StackOverflow 死掉的机会.
      • 也许只是提供一个简单的例子,将它用于一些非常基本的东西,应该只占用几行,但足以不使其成为仅链接。
      • @Qantas94Heavy,我刚刚做到了,推迟投票:)
      • @vitaly-t:可能有人将帖子标记为“质量非常低”,如果在处理标记之前编辑或删除帖子,则会自动投反对票。
      【解决方案3】:

      我们也可以使用postgresql-easy。 它建立在node-postgressqlutil 之上。 注意: pg_connection.jsyour_handler.js 在同一个文件夹中。 db.js 位于配置文件夹中。

      pg_connection.js

      const PgConnection = require('postgresql-easy');
      const dbConfig = require('./config/db');
      const pg = new PgConnection(dbConfig);
      module.exports = pg;
      

      ./config/db.js

      module.exports =  {
        database: 'your db',
        host: 'your host',
        port: 'your port',
        user: 'your user',
        password: 'your pwd',
      }
      

      your_handler.js

        const pg_conctn = require('./pg_connection');
      
        pg_conctn.getAll('your table')
          .then(res => {
               doResponseHandlingstuff();
            })
          .catch(e => {
               doErrorHandlingStuff()     
            })
      

      【讨论】:

        【解决方案4】:

        Slonik 是 Kuberchaun 和 Vitaly 提出的答案的替代方案。

        斯隆尼克实现safe connection handling;您创建一个连接池并为您处理连接打开/处理。

        import {
          createPool,
          sql
        } from 'slonik';
        
        const pool = createPool('postgres://user:password@host:port/database');
        
        return pool.connect((connection) => {
          // You are now connected to the database.
          return connection.query(sql`SELECT foo()`);
        })
          .then(() => {
            // You are no longer connected to the database.
          });
        

        postgres://user:password@host:port/database 是您的连接字符串(或者更规范的连接 URI 或 DSN)。

        这种方法的好处是您的脚本可以确保您永远不会意外离开挂起的连接。

        使用 Slonik 的其他好处包括:

        【讨论】:

          【解决方案5】:

          这是我用来将 node.js 连接到我的 Postgres 数据库的示例。

          我使用的node.js中的接口可以在这里找到https://github.com/brianc/node-postgres

          var pg = require('pg');
          var conString = "postgres://YourUserName:YourPassword@localhost:5432/YourDatabase";
          
          var client = new pg.Client(conString);
          client.connect();
          
          //queries are queued and executed one after another once the connection becomes available
          var x = 1000;
          
          while (x > 0) {
              client.query("INSERT INTO junk(name, a_number) values('Ted',12)");
              client.query("INSERT INTO junk(name, a_number) values($1, $2)", ['John', x]);
              x = x - 1;
          }
          
          var query = client.query("SELECT * FROM junk");
          //fired after last row is emitted
          
          query.on('row', function(row) {
              console.log(row);
          });
          
          query.on('end', function() {
              client.end();
          });
          
          
          
          //queries can be executed either via text/parameter values passed as individual arguments
          //or by passing an options object containing text, (optional) parameter values, and (optional) query name
          client.query({
              name: 'insert beatle',
              text: "INSERT INTO beatles(name, height, birthday) values($1, $2, $3)",
              values: ['George', 70, new Date(1946, 02, 14)]
          });
          
          //subsequent queries with the same name will be executed without re-parsing the query plan by postgres
          client.query({
              name: 'insert beatle',
              values: ['Paul', 63, new Date(1945, 04, 03)]
          });
          var query = client.query("SELECT * FROM beatles WHERE name = $1", ['john']);
          
          //can stream row results back 1 at a time
          query.on('row', function(row) {
              console.log(row);
              console.log("Beatle name: %s", row.name); //Beatle name: John
              console.log("Beatle birth year: %d", row.birthday.getYear()); //dates are returned as javascript dates
              console.log("Beatle height: %d' %d\"", Math.floor(row.height / 12), row.height % 12); //integers are returned as javascript ints
          });
          
          //fired after last row is emitted
          query.on('end', function() {
              client.end();
          });
          

          更新:-query.on 函数现已弃用,因此上述代码将无法按预期工作。作为解决方案,请查看:- query.on is not a function

          【讨论】:

          • 现在这就是我喜欢看到的示例类型。清晰且包含足够的代码。谢谢 JustBob。
          • 您在 pg_hba.conf 中添加了什么以允许来自 node.js 的连接?谢谢
          • host all all 0.0.0.0/0 md5 如果我没记错的话,这个条目将允许任何 IP 连接。请记住,这不是特定于节点的,而是特定于 PostgreSQL。同样在 postgresql.conf 我有listen_addresses ='*'。对于生产设置,请通读文档以确保您没有在任何地方开孔。我在我的开发设置中使用它,所以我可以允许任何机器连接。
          • 拼出的 conString 参数是天才,正是我所寻找的。谢谢!
          【解决方案6】:

          一个解决方案可以使用pool 的客户端,如下所示:

          const { Pool } = require('pg');
          var config = {
              user: 'foo', 
              database: 'my_db', 
              password: 'secret', 
              host: 'localhost', 
              port: 5432, 
              max: 10, // max number of clients in the pool
              idleTimeoutMillis: 30000
          };
          const pool = new Pool(config);
          pool.on('error', function (err, client) {
              console.error('idle client error', err.message, err.stack);
          });
          pool.query('SELECT $1::int AS number', ['2'], function(err, res) {
              if(err) {
                  return console.error('error running query', err);
              }
              console.log('number:', res.rows[0].number);
          });
          

          您可以在this resource查看更多详情。

          【讨论】:

          • 你没有使用'config'。
          【解决方案7】:

          只是为了添加一个不同的选项——我使用Node-DBI 连接到 PG,但也因为能够与 MySQL 和 sqlite 通信。 Node-DBI 还包括构建选择语句的功能,这对于动态执行动态操作非常方便。

          快速示例(使用存储在另一个文件中的配置信息):

          var DBWrapper = require('node-dbi').DBWrapper;
          var config = require('./config');
          
          var dbConnectionConfig = { host:config.db.host, user:config.db.username, password:config.db.password, database:config.db.database };
          var dbWrapper = new DBWrapper('pg', dbConnectionConfig);
          dbWrapper.connect();
          dbWrapper.fetchAll(sql_query, null, function (err, result) {
            if (!err) {
              console.log("Data came back from the DB.");
            } else {
              console.log("DB returned an error: %s", err);
            }
          
            dbWrapper.close(function (close_err) {
              if (close_err) {
                console.log("Error while disconnecting: %s", close_err);
              }
            });
          });
          

          config.js:

          var config = {
            db:{
              host:"plop",
              database:"musicbrainz",
              username:"musicbrainz",
              password:"musicbrainz"
            },
          }
          module.exports = config;
          

          【讨论】:

          • 嘿,mlaccetti,我在尝试连接并针对 SQLite3 数据库运行测试时遇到了类似的问题。我正在阅读一个教程,其中包含使用 DBWrapper 的说明,这就是我与您联系的原因。我的问题在这里:stackoverflow.com/q/35803874/1735836
          • Node-DBI 早已被废弃,不再受支持。
          • 谢谢,我的缺少database:参数,添加它终于修复了连接。
          猜你喜欢
          • 2016-06-18
          • 1970-01-01
          • 1970-01-01
          • 2013-11-21
          • 1970-01-01
          • 2019-08-11
          • 1970-01-01
          • 2018-07-20
          • 2016-05-03
          相关资源
          最近更新 更多