This is easy to do with pg-promise :
function buildTree(t) { return t.map('SELECT * FROM questions', [], q => { return t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id) .then(votes => { q.votes = votes; return q; }); }).then(t.batch);
API: map , any , task , batch
Related questions:
And if you want to use only one query, then using the syntax of PostgreSQL 9.4 and later, you can do the following:
SELECT json_build_object('id', q.id, 'content', q.content, 'votes', (SELECT json_agg(json_build_object('id', v.id, 'value', v.value)) FROM votes v WHERE q.id = v.question_id)) FROM questions q
And then your pg-promise example:
var query = `SELECT json_build_object('id', q.id, 'content', q.content, 'votes', (SELECT json_agg(json_build_object('id', v.id, 'value', v.value)) FROM votes v WHERE q.id = v.question_id)) json FROM questions q`; db.map(query, [], a => a.json) .then(data => { console.log(data); // your data tree }) .catch(error => { console.log(error); });
Conclusion
The choice between the two approaches above should be based on the performance requirements of your application:
- A single-query approach is faster, but difficult to read or extend, being rather verbose
- A multi-query approach is easier to understand and extend, but it is not very good for performance due to the dynamic number of queries executed.