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

我正在创build一个应用程序,用户可以创build问题,其他人可以upvote / downvote他们。

以下是我的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给了我一个投票join的问题,并会迫使我做服务器端操作,我不想这样做。

有没有办法做到这一点? 我的理由是什么,我想获得错误?

谢谢你的时间。

这很容易做到pg-promise :

 function buildTree(t) { return t.map('SELECT * FROM questions', [], q => { return t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id) .then(votes => { q.votes = votes; return q; }); }).then(t.batch); // settles the array of promises generated } db.task(buildTree) .then(data => { console.log(data); // your data tree }) .catch(error => { console.log(error); }); 

API: 地图 , 任何 , 任务 , 批次


相关问题:

  • 获得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诺言的例子是:

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

结论

上述两种方法之间的select应基于您的应用程序的性能要求:

  • 单一查询的方法更快,但有点难以阅读或扩展,相当冗长
  • 多查询方法更容易理解和扩展,但由于执行的查询的dynamic数量,性能不佳。