I am the author of pg-promise.
When you have 2 tables: Parent
-> Child
with 1-to-many relationship, and you want to get an array of matching Parent
rows, each row extended with property children
set to an array of the corresponding rows from table Child
...
There are several ways to accomplish this, as the combination of pg-promise and promises in general is very flexible. Here's the shortest version:
db.task(t => {
return t.map('SELECT * FROM Parent WHERE prop1 = $1', [prop1], parent => {
return t.any('SELECT * FROM Child WHERE parentId = $1', parent.id)
.then(children => {
parent.children = children;
return parent;
});
}).then(a => t.batch(a))
})
.then(data => {
/* data = the complete tree */
});
This is what we do there:
First, we query for Parent
items, then we map each row into a query for the corresponding Child
items, which then sets its rows into the Parent
and returns it. Then we use method batch to resolve the array of Child
queries returned from method map.
UPDATE for ES7
Here's the same as above, but using ES7 async
/await
syntax:
await db.task(async t => {
const parents = await t.any('SELECT * FROM Parent WHERE prop1 = $1', [prop1]);
for(const p of parents) {
p.children = await t.any('SELECT * FROM Child WHERE parentId = $1', [p.id]);
}
return parents;
});
// the task resolves with the correct data tree
The task will resolve with an array like this:
[
{
"parent1-prop1", "parent1-prop2",
"children": [
{"child1-prop1", "child1-prop2"},
{"child2-prop1", "child2-prop2"}
]
},
{
"parent2-prop1", "parent2-prop2",
"children": [
{"child3-prop1", "child3-prop2"},
{"child4-prop1", "child4-prop2"}
]
}
]
API references: map, batch
UPDATE
See a better answer to this: JOIN table as array of results with PostgreSQL/NodeJS.