You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pg-promise中将嵌套查询结果合并到父数组

解决PostgreSQL + pg-promise嵌套评论查询的问题

我来帮你搞定这个问题!你遇到的核心问题是异步Promise的处理不当——你的代码里直接把t.any返回的Promise赋值给了post.coments(注意这里拼写应该是comments哦),但没有等待这些Promise完成就返回了posts数组,所以最终返回的结果里评论数据根本没被正确填充。下面给你两种可行的解决方案:

方案一:修正异步Promise处理(基于原代码调整)

我们需要用Promise.all来等待所有评论查询的Promise完成,确保每个帖子的评论都被正确赋值后再返回结果:

con.task(t => {
  return t.any(
    'select *, avatar from post, users where usuario = $1 and usuario = alias ORDER BY time DESC LIMIT 10 OFFSET $2',
    [username, pos]
  ).then(posts => {
    if (posts.length === 0) return posts;
    
    // 把每个帖子转换成一个Promise,负责获取并填充评论
    const postWithCommentsPromises = posts.map(post => {
      return t.any('select * from comment where idPost = $1', post.id)
        .then(comments => {
          post.comments = comments; // 修正拼写错误:coments → comments
          return post;
        });
    });
    
    // 等待所有评论查询完成,返回填充好的帖子数组
    return Promise.all(postWithCommentsPromises);
  });
})
.then(posts => {
  res.send(posts);
})
.catch(error => {
  console.error('查询出错:', error);
  res.status(500).send('服务器内部错误');
});

关键说明:

  • posts.map会把每个帖子转换成一个Promise,这个Promise先执行评论查询,再把结果赋值给帖子的comments属性
  • Promise.all会等待所有这些Promise全部完成,最终得到的是已经填充好评论的完整帖子数组

方案二:数据库层面聚合查询(更高效推荐)

上面的方案需要执行1(帖子查询)+ N(评论查询)次数据库请求,当帖子数量多的时候性能会受影响。更优的方式是用PostgreSQL的JSON_AGG函数,一次查询就把帖子和对应的评论嵌套好:

con.task(t => {
  return t.any(`
    SELECT 
      p.*, 
      u.avatar,
      -- 聚合评论为JSON数组,没有评论时返回空数组
      COALESCE(JSON_AGG(c) FILTER (WHERE c.id IS NOT NULL), '[]') AS comments
    FROM post p
    JOIN users u ON p.usuario = u.alias
    -- LEFT JOIN确保没有评论的帖子也能被返回
    LEFT JOIN comment c ON p.id = c.idPost
    WHERE p.usuario = $1
    GROUP BY p.id, u.avatar
    ORDER BY p.time DESC
    LIMIT 10 OFFSET $2;
  `, [username, pos]);
})
.then(posts => {
  res.send(posts);
})
.catch(error => {
  console.error('查询出错:', error);
  res.status(500).send('服务器内部错误');
});

关键说明:

  • LEFT JOIN关联帖子和评论,保证即使没有评论的帖子也会出现在结果里
  • JSON_AGG(c)把每个帖子对应的所有评论聚合为一个JSON数组
  • COALESCE(..., '[]')确保没有评论的帖子返回的是[]而不是null,前端处理更友好
  • 只需要一次数据库请求,性能远优于多次查询的方案

另外还要提醒你:原SQL里的where user= $1应该是where usuario = $1,因为你的post表字段是usuario,否则会出现字段不存在的错误哦!

内容的提问来源于stack exchange,提问作者Sergio Rey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:22:45