【问题标题】:pg-promise task and map with multiple same level nested queries具有多个相同级别嵌套查询的 pg-promise 任务和映射
【发布时间】:2017-08-29 06:07:51
【问题描述】:

我正在使用 node 和 pg-promise 创建一个基本的 rest API,并且在查询特定用户的所有数据时遇到了一些问题。下面是返回的数据应该是什么样子。地址、电话号码和技能都位于不同的表格中。我在检索地址或电话号码时没有问题,这只是我似乎无法获得的技能。不太确定如何在让用户获取所有其他字段的主查询之后进行多个查询,请参阅随附的代码以供参考,我很乐意回答任何问题。


{
"user_id": 1,
"first_name": "Eugene",
"last_name": "Hanson",
"display_name": "Eugene Hanson",
"email": "ehanson0@typepad.com",
"hash": "88a6aa27235d2e39dd9cb854cc246487147050f265578a3e1aee35be5db218ef",
"privilege_id": 14,
"seniority": 1,
"birthday": "19-11-1940 00:00:00.0",
"shift_count_total": 587,
"shift_count_year": 62,
"address_id": 1,
"street": "92 Schmedeman Lane",
"city": "Fort Smith",
"state": "AR",
"zip": 72905,
"phone_numbers": [
  {
    "phone_number": "62-(705)636-2916",
    "name": "PRIMARY"
  }
],
"skills": [
    "Head Audio",
    "Head Video",
    "Head Electrician",
    "Carpenter",
    "rigger"
    ]
}

    function getAllUsers() {
    // console.time("answer time")
    var deferred = Q.defer();
    db.task(t => {
        return t.map('SELECT * \
                        FROM users \
                        JOIN addresses \
                        ON users.address_id = addresses.address_id',[], user => {
            var user_id = user.user_id;
            // console.log(user_id)
            console.time("answer time")
            return t.manyOrNone('SELECT phone_numbers.phone_number, phone_types.name \
                                    FROM users \
                                    JOIN users_phone_numbers \
                                    ON users.user_id = users_phone_numbers.user_id \
                                    JOIN phone_numbers \
                                    ON users_phone_numbers.phone_id = phone_numbers.phone_id \
                                    JOIN phone_types \
                                    ON phone_numbers.phone_type_id = phone_types.phone_type_id \
                                    WHERE users.user_id = $1', user.user_id)
                                    .then(phone_numbers=> {
                                        // logger.log('info', phone_numbers)
                                        user.phone_numbers = phone_numbers;
                                        return user;
                                    })
        }).then(t.batch);
    })
    .then(data => {
        // console.log(data)
        console.timeEnd("answer time");
        var response = {code: "200", 
                        message: "", 
                        payload: data};
        deferred.resolve(response);
    })
    .catch(error => {
    var response = {code: error.code, 
                    message: error.message, 
                    payload: ""};
    logger.log('error', error)
    deferred.reject(response)
});

【问题讨论】:

  • 问题是什么?你会得到什么?你的.catch 处理程序在哪里?您需要正确完成您的问题,然后才能回答;)
  • 编辑了原始帖子以包含在我的复制和粘贴中意外遗漏的.catch。抱歉,我的问题不清楚,我要做的是遍历所有用户,然后从其他各种表中获取所有相关数据,然后将其合并回用户记录并将其发送回客户端。我目前只能对带有地图的电话号码执行此操作,不确定如何添加另一个查询以在地图中使用来表示获取技能。欢迎任何建议,如果我需要澄清更多信息,请随时告诉我。
  • 我会探索让我的 SQL 变得更复杂;在代码中使用一些 LEFT JOIN 和 .reduce()。可能还可以使用 postgres 的 array_agg lorenstewart.me/2017/12/04/postgresqls-array_agg-function,它看起来可以帮助您对查询中的关系数据进行反规范化。

标签: javascript node.js postgresql pg-promise


【解决方案1】:

我是pg-promise的作者。


您的函数的简化版本是:

function getAllUsers() {
    return db.task(t => {
        return t.map('SELECT * FROM users', [], user => {
            return t.batch([
                t.any('SELECT * FROM phones'), // plus formatting params
                t.any('SELECT * FROM skills'), // plus formatting params
            ])
                .then(data => {
                    user.phones = data[0];
                    user.skills = data[1];
                    return user;
                });
        }).then(t.batch);
    });
}

getAllUsers()
    .then(data => {
        // data tree
    })
    .catch(error => {
        // error
    });

如果你使用bluebird作为promise库,那么你可以替换这个代码:

.then(data => {
    user.phones = data[0];
    user.skills = data[1];
    return user;
});

用这个:

.spread((phones, skills) => {
    user.phones = phones;
    user.skills = skills;
    return user;
});

不要使用var deferred = Q.defer(); 之类的东西,那里不需要它。该库已经基于 Promise。

有关高性能替代方案,请参阅:get JOIN table as array of results with PostgreSQL/NodeJS

【讨论】:

  • 谢谢 这正是我所需要的,我在互联网上到处寻找如何将这些部分组合在一起,但找不到一个清晰的想法,你能够阐明它。
  • @seanpdiaz 欢迎您。我已经更新了答案;)
  • 感谢您为我指出正确的方向,让我的通话更高效,我能够使用您提供的链接,将我的响应时间从 12,000 毫秒缩短到 500 毫秒以下。再次谢谢
猜你喜欢
  • 2017-03-09
  • 1970-01-01
  • 2012-02-21
  • 2017-05-30
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 2017-11-12
  • 1970-01-01
相关资源
最近更新 更多