-
Notifications
You must be signed in to change notification settings - Fork 217
Chaining Queries
When executing a single query, you normally use query methods of the Database object directly:
db.one('select * from users where id = $1', 123)
.then(data => {
// success;
})
.catch(error => {
// error;
});
All methods underneath use method query, which allocates and releases the connection, so chaining them directly will result in poor connection usage, compromising performance and scalability.
Instead, you should use method task, which allocates and releases the connection only once, providing a connection context well suited for executing multiple queries at once:
db.task(t => {
return t.one('SELECT id FROM Users WHERE name = $1', 'John')
.then(user => {
return t.any('SELECT * from Events WHERE userId = $1', user.id);
});
})
.then(events => {
// success
})
.catch(error => {
// error
});
And if the task requires a transaction, use method tx instead.
If you do not follow the advised approach, your application will perform better under a small load, due to more connections allocated in parallel, but under a heavy load it will quickly deplete the connection pool, crippling performance and scalability of your application.
- Tasks also simplify the use of the new ES6/ES7 syntax...
- Tagged tasks and transactions are easier to read and monitor via pg-monitor, see tags.
ES6
db.task('my-es6-task', function * (t) => {
const user = yield t.one('SELECT id FROM Users WHERE name = $1', 'John');
return yield t.any('SELECT * from Events WHERE userId = $1', user.id);
})
.then(events => {
// success
})
.catch(error => {
// error
});
ES7
db.task('my-es7-task', async t => {
const user = await t.one('SELECT id FROM Users WHERE name = $1', 'John');
return await t.any('SELECT * from Events WHERE userId = $1', user.id);
})
.then(events => {
// success
})
.catch(error => {
// error
});
pg-promise