What is the proper way to use the node.js postgresql module?
postgresql - How to make connection to Postgres via Node.js - Stack Overflow
PostgresJs: PostgreSQL client for Node.js and Deno
Node.js with Postgresql Bad Practice
Videos
Raw queries, ORM, Query builder, code generators etc which pg client library would you choose with Node.js today in production?
Popular ones are: 1] Knex 2] Sequalize 3] TypeORM 4] Prisma 5] Drizzle 6] MikroORM
If you can also comment on "why" that would also be great. If there is any new recommendation that is also great
I'm the author of node-postgres. First, I apologize the documentation has failed to make the right option clear: that's my fault. I'll try to improve it. I wrote a Gist just now to explain this because the conversation grew too long for Twitter.
Using
pg.connectis the way to go in a web environment.PostgreSQL server can only handle 1 query at a time per connection. That means if you have 1 global
new pg.Client()connected to your backend your entire app is bottleknecked based on how fast postgres can respond to queries. It literally will line everything up, queuing each query. Yeah, it's async and so that's alright...but wouldn't you rather multiply your throughput by 10x? Usepg.connectset thepg.defaults.poolSizeto something sane (we do 25-100, not sure the right number yet).
new pg.Clientis for when you know what you're doing. When you need a single long lived client for some reason or need to very carefully control the life-cycle. A good example of this is when usingLISTEN/NOTIFY. The listening client needs to be around and connected and not shared so it can properly handleNOTIFYmessages. Other example would be when opening up a 1-off client to kill some hung stuff or in command line scripts.
One very helpful thing is to centralize all access to your database in your app to one file. Don't litter pg.connect calls or new clients throughout. Have a file like db.js that looks something like this:
module.exports = {
query: function(text, values, cb) {
pg.connect(function(err, client, done) {
client.query(text, values, function(err, result) {
done();
cb(err, result);
})
});
}
}
This way you can change out your implementation from pg.connect to a custom pool of clients or whatever and only have to change things in one place.
Have a look at the node-pg-query module that does just this.
I am the author of pg-promise, which simplifies the use of node-postgres via promises.
It addresses the issues about the right way of connecting to and disconnecting from the database, using the connection pool implemented by node-postgres, among other things, like automated transactions.
An individual request in pg-promise boils down to just what's relevant to your business logic:
db.any('SELECT * FROM users WHERE status = $1', ['active'])
.then(data => {
console.log('DATA:', data);
})
.catch(error => {
console.log('ERROR:', error);
});
i.e. you do not need to deal with connection logic when executing queries, because you set up the connection only once, globally, like this:
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;
You can find many more examples in Learn by Example tutorial, or on the project's home page.
Here is an example I used to connect node.js to my Postgres database.
The interface in node.js that I used can be found here 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();
});
UPDATE:- THE query.on function is now deprecated and hence the above code will not work as intended. As a solution for this look at:- query.on is not a function
A modern and simple approach: 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]);
See also: How to correctly declare your database module.