使用 pg-promise 获取父子树
Get a parents + children tree with pg-promise
我将 pg-promise
库与 bluebird
一起用于进行相关查询。
我有两个 tables,a 和 b,看起来像这样:
| a | | b |
|-------| |-------|
| a_id | | b_id |
| prop1 | | prop2 |
| b_a |
其中 b.b_a
是对 a.a_id
的引用。我想 select 匹配给定 prop1
的所有条目,结果应包含所有匹配的 a
-行加上每个 a
对应的 b
-行。这应该可以通过两个相关查询来实现。两个查询都可能 return 多个结果。
如果 table a
只有 return 一行,我可以这样做:
function getResult(prop1) {
return db.task(function (t) {
return t.one("select * from a where prop1=", prop1)
.then(function (a) {
return t.batch([a, t.any("select * from b where b_a=", a.a_id)]);
})
.then(function (data) {
var a = data[0];
var bs = data[1];
bs.forEach(function (b) {
b.a = a;
});
return bs;
});
});
}
而且我还能够为多个 a
-结果获得所有匹配的 b
-条目,如下所示:
function getResult(prop1) {
return db.task(function (t) {
return t.many("select * from a where prop1=", prop1)
.then(function (as) {
var queries = [];
as.forEach(function (a) {
queries.push(t.any("select * from b where b_a=", a.id));
});
return t.batch(queries); // could concat queries with as here, but there wouldn't be a reference which b row belongs to which a row
})
.then(function (data) {
// data[n] contains all matching b rows
});
});
}
但是如何将这两者结合起来呢?
我是 pg-promise 的作者。
当你有 2 个 table 时:Parent
-> Child
具有一对多关系,并且你想获得匹配的数组 Parent
行,每行扩展 属性 children
设置为来自 table Child
...
的相应行的数组
有几种方法可以实现这一点,因为 pg-promise 和 promises 的组合通常非常灵活。这是最短的版本:
db.task(t => {
return t.map('SELECT * FROM Parent WHERE prop1 = ', [prop1], parent => {
return t.any('SELECT * FROM Child WHERE parentId = ', parent.id)
.then(children => {
parent.children = children;
return parent;
});
}).then(a => t.batch(a))
})
.then(data => {
/* data = the complete tree */
});
这就是我们在那里所做的:
首先,我们查询 Parent
项,然后将每一行映射到对相应 Child
项的查询中,然后将其行设置到 Parent
和 returns它。然后我们使用方法 batch to resolve the array of Child
queries returned from method map.
ES7 更新
这里和上面一样,但是使用ES7 async
/await
语法:
await db.task(async t => {
const parents = await t.any('SELECT * FROM Parent WHERE prop1 = ', [prop1]);
for(const p of parents) {
p.children = await t.any('SELECT * FROM Child WHERE parentId = ', [p.id]);
}
return parents;
});
// the task resolves with the correct data tree
任务将通过这样的数组解决:
[
{
"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"}
]
}
]
更新
看到一个更好的答案:。
我将 pg-promise
库与 bluebird
一起用于进行相关查询。
我有两个 tables,a 和 b,看起来像这样:
| a | | b |
|-------| |-------|
| a_id | | b_id |
| prop1 | | prop2 |
| b_a |
其中 b.b_a
是对 a.a_id
的引用。我想 select 匹配给定 prop1
的所有条目,结果应包含所有匹配的 a
-行加上每个 a
对应的 b
-行。这应该可以通过两个相关查询来实现。两个查询都可能 return 多个结果。
如果 table a
只有 return 一行,我可以这样做:
function getResult(prop1) {
return db.task(function (t) {
return t.one("select * from a where prop1=", prop1)
.then(function (a) {
return t.batch([a, t.any("select * from b where b_a=", a.a_id)]);
})
.then(function (data) {
var a = data[0];
var bs = data[1];
bs.forEach(function (b) {
b.a = a;
});
return bs;
});
});
}
而且我还能够为多个 a
-结果获得所有匹配的 b
-条目,如下所示:
function getResult(prop1) {
return db.task(function (t) {
return t.many("select * from a where prop1=", prop1)
.then(function (as) {
var queries = [];
as.forEach(function (a) {
queries.push(t.any("select * from b where b_a=", a.id));
});
return t.batch(queries); // could concat queries with as here, but there wouldn't be a reference which b row belongs to which a row
})
.then(function (data) {
// data[n] contains all matching b rows
});
});
}
但是如何将这两者结合起来呢?
我是 pg-promise 的作者。
当你有 2 个 table 时:Parent
-> Child
具有一对多关系,并且你想获得匹配的数组 Parent
行,每行扩展 属性 children
设置为来自 table Child
...
有几种方法可以实现这一点,因为 pg-promise 和 promises 的组合通常非常灵活。这是最短的版本:
db.task(t => {
return t.map('SELECT * FROM Parent WHERE prop1 = ', [prop1], parent => {
return t.any('SELECT * FROM Child WHERE parentId = ', parent.id)
.then(children => {
parent.children = children;
return parent;
});
}).then(a => t.batch(a))
})
.then(data => {
/* data = the complete tree */
});
这就是我们在那里所做的:
首先,我们查询 Parent
项,然后将每一行映射到对相应 Child
项的查询中,然后将其行设置到 Parent
和 returns它。然后我们使用方法 batch to resolve the array of Child
queries returned from method map.
ES7 更新
这里和上面一样,但是使用ES7 async
/await
语法:
await db.task(async t => {
const parents = await t.any('SELECT * FROM Parent WHERE prop1 = ', [prop1]);
for(const p of parents) {
p.children = await t.any('SELECT * FROM Child WHERE parentId = ', [p.id]);
}
return parents;
});
// the task resolves with the correct data tree
任务将通过这样的数组解决:
[
{
"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"}
]
}
]
更新
看到一个更好的答案: