11

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

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 中)

4

1 回答 1

31

pg-promise文档有大量关于如何执行多个查询的示例。

初始化

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
    });

当查询改变数据时,我们应该tx替换task来进行交易。

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

当您需要对每个 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

于 2016-03-02T12:27:19.970 回答