如何通过Node.js连接Postgres数据库

132

我正尝试创建一个PostgreSQL数据库,因此我安装了PostgreSQL并使用initdb /usr/local/pgsql/data启动了服务器,然后使用postgres -D /usr/local/pgsql/data启动了该实例。现在我该如何通过Node与其交互呢?例如,connectionstring是什么,或者我如何能够找到它。

7个回答

325

这是一个我用来连接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


26
这正是我喜欢看到的类型。清晰明了,并包含足够的代码。感谢JustBob。 - Stradas
1
你在pg_hba.conf中添加了什么以允许来自node.js的连接?谢谢。 - Marius
3
这个条目,如果我没记错的话,将允许任何IP连接。需要注意的是,这不是针对特定节点,而是针对PostgreSQL的。此外,在postgresql.conf中,我设置了listen_addresses = '*'。对于生产环境,请仔细阅读文档,确保没有在任何地方开放漏洞。我在我的开发环境中使用这个设置,所以允许任何机器连接对我来说都没问题。 - Kuberchaun
1
conString参数的详细说明非常巧妙,正是我所需要的。谢谢! - nelsonenzo
2
小心!通过构造函数创建的客户端实例不参与连接池。 - ma11hew28
显示剩余7条评论

36

现代简单的方法: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]);

另请参阅:如何正确声明您的数据库模块


虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - arulmr
1
在理想的世界中 - 是的,然而,正如您在上面所看到的,被接受的答案只是一个链接。就像那里一样,从链接提供的信息中制作摘要会太过繁琐,考虑到这两个链接都是给GitHub的公共存储库,它们失效的可能性不会比StackOverflow失效的可能性更大。 - vitaly-t
也许只需提供一个简单的示例来演示如何使用它进行一些非常基本的操作,这应该只需要几行代码,但足以避免仅提供链接。 - Qantas 94 Heavy
@Qantas94Heavy,我们刚刚完成了,先别急着点踩它 :) - vitaly-t
回答已经改进了好几次。有没有人能撤销这个负评?它确实完美地回答了问题。谢谢! - vitaly-t
显示剩余2条评论

13

只是补充一个不同的选项 - 我使用Node-DBI连接到PG,但也可以连接到MySQL和sqlite。 Node-DBI还包括构建select语句的功能,这对于在运行时进行动态操作非常方便。

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

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的指令进行教程,这就是我联系你的原因。我的问题在这里:http://stackoverflow.com/q/35803874/1735836。 - Patricia
Node-DBI 已经被废弃很久了,不再受支持。 - vitaly-t
谢谢,我的代码缺少了 database: 参数,最终添加上它修复了连接。 - RAM237

5

一个解决方案是使用如下的客户端池: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);
});

您可以在这个资源上查看更多细节。

你没有使用'config'。 - LEMUEL ADANE

2

连接字符串

连接字符串是一个形如以下格式的字符串:

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的指南。


1

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

Slonik 实现了 安全连接处理;您可以创建一个连接池,连接的打开/处理将由 Slonik 自动完成。

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 的其他好处包括:

"

0
我们还可以使用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()     
      })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接