当前位置: 首页 > 面试题库 >

使用PostgreSQL / NodeJS获取JOIN表作为结果数组

慕容渊
2023-03-14
问题内容

我正在创建一个应用程序,用户可以在其中创建问题,其他人可以对其进行投票。

以下是我的SQL模式的一部分:

CREATE TABLE "questions" (
  id            SERIAL,
  content       VARCHAR(511) NOT NULL,
  created_at    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
  CONSTRAINT    pk_question PRIMARY KEY (id)
);

CREATE TABLE "votes" (
  id            SERIAL,
  value         INT,
  question_id   INT NOT NULL,
  CONSTRAINT    pk_vote PRIMARY KEY (id),
  CONSTRAINT    fk_question_votes FOREIGN KEY (question_id) REFERENCES questions (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE
);

我想要的是Postgres给我每个问题一个投票,就像这样:

[{ // a question
  id: 1,
  content: 'huh?',
  votes: [{ // a vote
    id: 1,
    value: 1
  }, { // another vote
    id: 2,
    value: -1
  }]
}, { /*another question with votes*/ }]

我查看了聚合函数(例如array_agg()),但它仅提供了值。JOIN给我一个问题,并投了赞成票,这将迫使我进行服务器端操作,而我不希望这样做。

有什么办法吗?我对我想要得到的东西的推理是错误的吗?

谢谢你的时间。


问题答案:

使用pg-promise很容易做到:

function buildTree(t) {
    const v = q => t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id)
        .then(votes => {
            q.votes = votes;
            return q;
        });

    return t.map('SELECT * FROM questions', [], v).then(t.batch);
}

db.task(buildTree)
    .then(data => {
        console.log(data); // your data tree
    })
    .catch(error => {
        console.log(error);
    });

API:map,any,task,batch

相关问题:

  • 用pg-promise获得父母和孩子的树
  • pg-promise的条件任务

而且,如果您只想使用一个查询,那么使用PostgreSQL 9.4和更高版本的语法,您可以执行以下操作:

SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
    (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
     FROM votes v WHERE q.id = v.question_id))
FROM questions q

然后,您的pg-promise示例将是:

const query =
    `SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
        (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
         FROM votes v WHERE q.id = v.question_id)) json
    FROM questions q`;

db.map(query, [], a => a.json)
    .then(data => {
        console.log(data); // your data tree
    })
    .catch(error => {
        console.log(error);
    });

而且,您肯定希望将这样复杂的查询保留在外部SQL文件中。请参阅查询文件。

结论

上面介绍的两种方法之间的选择应基于您的应用程序的性能要求:

  • 单查询方法速度更快,但是有点冗长,但难以读取或扩展
  • 多查询方法更易于理解和扩展,但由于执行的查询数量动态,因此性能不佳。


 类似资料:
  • 我想使用以下查询获得结果列表: 我在它的实体类中使用了它,但我得到了异常: 当用户成功登录应用程序时,将获得matricula字段。应该通过CDI在NamedQuery中设置它来查询数据库。matricula字段位于另一个不同于此处映射的表中。 如何设置注入的setsionChave字符串在参数的矩阵,这是XRlzConsolado类类型? 豆子: 有3个实体:XRlz、XRlzConsolado

  • 问题内容: 我正在寻找一个返回列表的t-sql脚本,该列表显示来自Table1分组的每个第二个值。 例如,我有以下数据(表1),并想要所需的结果列表: 所需的摘要列表: 我考虑使用“选择不同的和左外部联接”来做某事,但是我无法使其正常工作。可能我需要一个行编号,但无法弄清楚该怎么做。有人可以帮助我吗? 下面是我用来制作和填充Table1的脚本: 问题答案: 您可以使用和: 怎么运行的: 使用会根据

  • 问题内容: 我需要从结果对象获取所有行。我正在尝试建立一个将容纳所有行的新数组。 这是我的代码: 应该是包含所有行的新数组,但是我得到一个空数组。 任何想法为什么会这样? 问题答案: 您有一个轻微的语法问题,即错误的分号。 注意结尾的分号吗?这意味着后面的程序段不是循环执行的。摆脱它,它应该可以工作。 另外,您可能需要检查查询是否确实有效:

  • 我有三张桌子: 表名:流派 表字段:id、名称 例1,行动 我试图有一个查询,得到所有的信息从动漫,也得到我的动漫的流派名称。 我有以下疑问: 这让我得到了动漫信息和所有流派的主要ID,但我没有他们的名字。 我一直在研究,但也许我做得不对。 顺便说一句,“动漫”是一个电视节目,所以它可以有多种流派,一对多的关系。

  • 我不熟悉使用CRUD存储库。 我有一个包含三列的数据库表: course_id,姓名,当然 我想得到一份course\u id name的列表,例如, 但是,我不想使用查询,而是使用crud存储库。 我的控制器显示有错误。我可以知道有这个错误吗? 我的控制器 服务 存储库

  • 问题内容: 我想让PostgreSQL将查询结果作为一个JSON数组返回。给定 我想要类似的东西 要么 (实际上,同时了解两者会更有用)。我尝试过一些类似的事情 而且我觉得我很亲近,但真的不在那儿。我是否应该查看9.15以外的其他文档。JSON函数和运算符? 顺便说一下,我不确定我的想法。这是通常的设计决定吗?我的想法是,我当然可以接受上述3个查询中的第一个查询的结果(例如),并在将其提供给客户端