使用 pg-promise 查询多对多关系的最佳方法
Best way to query a Many to Many Relationship using pg-promise
例如,我想从数据库中获取用户信息、电子邮件及其角色,并创建一个对象,如:
{
"id": 1,
"firstname": "John",
"lastname": "Johnny",
"emails": [
{
"type": "work",
"email": "work@work.com"
},
{
"type": "personal",
"email": "personal@personal.com"
}
],
"roles": [
{
"role": "ADM",
"title": "Admin"
},
{
"role": "PUB",
"title": "Publisher"
}
]
}
我需要查询三个table:
Users
table 有 id
, firstname
,lastname
.
Emails
table 有 type
, email
,user_id
.
Roles
table 有 role
, title
,user_id
.
基于 pg-promise's wiki I am almost sure it has to be done using Tasks 但不确定如何链接它们。
UPDATE 在我的实际项目中,我必须插入一个产品并使用生成的 id 来插入属性。如果您遇到类似情况,请在此处添加我的代码:
//Insert a new product with attribites as key value pairs
post_product_with_attr: function(args) {
return db.task(function(t) {
return t.one(sql.post_new_product, args)
.then(function(dt) {
var queries = [];
Object.keys(args).forEach(function(key) {
queries.push(t.one(sql.post_attr_one, { Id: dt.id, key: key, value: args[key] }));
});
return queries.length ? t.batch(queries) : [dt];
});
});
}
您描述的不是多对多关系,而是 2 个一对多关系。
Based on the pg-promise's wiki I am almost sure it has to be done using Tasks but not sure how would you chain them.
在您的示例中,无需链接任何内容。当一个结果需要用作下一个的条件时,一个链承诺,因为这就是承诺的工作方式,而不仅仅是查询。
因此,您可以并行或独立执行所有 3 个查询,如下例所示:
function getUserInfo(userId) {
return db.task(async t => {
const user = await t.one('SELECT id, firstname, lastname FROM Users WHERE id = ', userId);
const emails = await t.any('SELECT type, email FROM emails WHERE user_id = ', userId),
const roles = await t.any('SELECT role, title FROM roles WHERE user_id = ', userId);
user.emails = emails;
user.roles = roles;
return user;
});
用法示例:
const user = await getUserInfo(123); //=> user object with all details
请注意,通过现有的 PostgreSQL JSON 函数执行此操作效率更高,这样您就可以只执行一个查询。
例如,我想从数据库中获取用户信息、电子邮件及其角色,并创建一个对象,如:
{
"id": 1,
"firstname": "John",
"lastname": "Johnny",
"emails": [
{
"type": "work",
"email": "work@work.com"
},
{
"type": "personal",
"email": "personal@personal.com"
}
],
"roles": [
{
"role": "ADM",
"title": "Admin"
},
{
"role": "PUB",
"title": "Publisher"
}
]
}
我需要查询三个table:
Users
table 有id
,firstname
,lastname
.Emails
table 有type
,email
,user_id
.Roles
table 有role
,title
,user_id
.
基于 pg-promise's wiki I am almost sure it has to be done using Tasks 但不确定如何链接它们。
UPDATE 在我的实际项目中,我必须插入一个产品并使用生成的 id 来插入属性。如果您遇到类似情况,请在此处添加我的代码:
//Insert a new product with attribites as key value pairs
post_product_with_attr: function(args) {
return db.task(function(t) {
return t.one(sql.post_new_product, args)
.then(function(dt) {
var queries = [];
Object.keys(args).forEach(function(key) {
queries.push(t.one(sql.post_attr_one, { Id: dt.id, key: key, value: args[key] }));
});
return queries.length ? t.batch(queries) : [dt];
});
});
}
您描述的不是多对多关系,而是 2 个一对多关系。
Based on the pg-promise's wiki I am almost sure it has to be done using Tasks but not sure how would you chain them.
在您的示例中,无需链接任何内容。当一个结果需要用作下一个的条件时,一个链承诺,因为这就是承诺的工作方式,而不仅仅是查询。
因此,您可以并行或独立执行所有 3 个查询,如下例所示:
function getUserInfo(userId) {
return db.task(async t => {
const user = await t.one('SELECT id, firstname, lastname FROM Users WHERE id = ', userId);
const emails = await t.any('SELECT type, email FROM emails WHERE user_id = ', userId),
const roles = await t.any('SELECT role, title FROM roles WHERE user_id = ', userId);
user.emails = emails;
user.roles = roles;
return user;
});
用法示例:
const user = await getUserInfo(123); //=> user object with all details
请注意,通过现有的 PostgreSQL JSON 函数执行此操作效率更高,这样您就可以只执行一个查询。