【问题标题】:How to get results from multiple queries at once with pg-promise?如何使用 pg-promise 一次从多个查询中获取结果?
【发布时间】:2016-06-14 17:43:54
【问题描述】:

目前我有以下代码来获取两个查询的结果

dbro.many("SELECT geoname_id, country_name FROM paises WHERE locale_code=$1 LIMIT 10",data.lang)
   .then(function(countriesData){
      data.countries=countriesData;
      dbro.many("SELECT * FROM categorias")
       .then(function(categoriesData){
         data.categories=(categoriesData)
         console.log(data);
         res.render('layout', data);
         res.end();
      })
       .catch(function(err){
        console.log("error while fetching categories data");
      })
    })
    .catch(function(err){
      console.log("error while fetching countries data",err);
    });

不知何故,我认为这是不对的。如果我需要在返回回调之前获取许多查询的结果怎么办?几个 then/catch 的嵌套变得可怕。目标是在渲染页面之前准备好所有数据(在 Express 中)

【问题讨论】:

    标签: javascript pg-promise


    【解决方案1】:

    pg-promise 文档有 plenty of examples 说明如何执行多个查询。

    初始化

    const pgp = require('pg-promise')(/* initialization options */);
    const db = pgp('postgres://username:password@host:port/database');
    

    当查询相互依赖时,我们应该使用任务:

    db.task('get-user-events', async t => {
            const user = await t.one('select * from users where id = $1', 123);
            return t.any('select * from events where login = $1', user.name);
    })
        .then(data => {
            // data = result from the last query;
        })
        .catch(error => {
            // error
        });
    

    当查询之间没有依赖关系时:

    db.task('get-everything', async t => {
        const users = await t.any('select * from users');
        const count = await t.one('select count(*) from events', [], a => +a.count);
        return {users, count};
    })
        .then({users, count} => {
    
        })
        .catch(error => {
            // error
        });
    

    当查询更改数据时,我们应该task替换为tx进行事务处理。

    请注意,我用 “应该” 强调了每个语句,因为您可以执行任务或事务之外的所有内容,但由于管理数据库连接的方式,不建议这样做。

    应该仅在需要对每个 HTTP 请求执行单个查询时对根协议(db 对象)执行查询。一次应该始终在任务/事务中执行多个查询。

    另见Chaining Queries,其要点在底部:

    如果您不遵循建议的方法,由于并行分配的连接更多,您的应用程序在小负载下会表现得更好,但在重负载下它会迅速耗尽连接池,削弱应用程序的性能和可扩展性.

    更新

    pg-promise v7.0.0 开始,我们可以在一个命令中从多个独立查询中提取结果,这比之前的所有解决方案都高效:

    const {users, count} = await db.multi('SELECT * FROM users;SELECT count(*) FROM events');
    

    该库实现helpers.concat,以格式化和连接多个查询。

    另见方法:multimultiResult

    【讨论】:

    • 谢谢,这正是我想要的。我确实阅读了文档,但我错过了关键部分(至少对我来说): // data[0] = result from the first query; // data[1] = 第二个查询的结果; (结果数据为数组)
    • @vitaly-t 感谢您的示例。但是,如果您必须将两者混合使用,您会怎么做?在我的任务中,我运行 5 个独立查询。每个都返回最新的插入 id。完成此任务后,我需要运行最后一个查询,该查询将使用该任务生成的所有 id。到目前为止,我还没有设法将两者混合在一起。你有什么主意吗。感谢您的帮助。
    • @Stanislasdrg 你所问的更多是关于 Promise 的基本使用而不是这个库。你做return t.batch([...your 5 inserts...]).then(data=>t.query(...query based on data...))
    • @vitaly-t 谢谢你的例子。你将如何做一个更复杂的链条?例如“获取所有名为 john 的用户”,然后“获取他们孩子的名字”并返回为 [{ firstname:"John", lastname:"dep", children:[{name:...},{...}] } ,{ ... ]
    • @PirateApp 不,会由catch在任务上处理。
    猜你喜欢
    • 2017-07-22
    • 2017-10-14
    • 2021-08-08
    • 2017-10-03
    • 2019-03-11
    • 1970-01-01
    • 2019-01-04
    • 2016-11-14
    • 2023-03-23
    相关资源
    最近更新 更多