我将从顶部开始......我有两张桌子,引号和评论。一句话有很多'评论。我的最终目标是在前端有两个.map()函数,一个用于将所有引号呈现给我的页面,另一个用于呈现位于其上方的引用的每个注释。
我试图从psql中检索一个返回类似内容的json:
[
{
"id": 1,
"content": "quote number 1!",
"name": null,
"num_of_flags": null,
"comments": [
{
"id": 1,
"comment_content": "comment one!",
"num_of_likes": null,
"quote_id": 1
},
{
"id": 1,
"comment_content": "comment 2!",
"num_of_likes": null,
"quote_id": 1
}
]
这样,'引用'是一个对象数组,属于它的注释也是如此。
以下是我实际回复的内容:
[
{
"id": 1,
"content": "quote number 1!",
"name": null,
"num_of_flags": null,
"comments": [
{
"id": 1,
"comment_content": "comment 1!",
"num_of_likes": null,
"quote_id": 1
}
]
},
{
"id": 2,
"content": "quote number 2!",
"name": null,
"num_of_flags": null,
"comments": [
{
"id": 2,
"comment_content": "comment 2!",
"num_of_likes": null,
"quote_id": 2
}
]
},
{
"id": 3,
"content": "quote number 3!",
"name": null,
"num_of_flags": null,
"comments": [
{
"id": 3,
"comment_content": "comment 3",
"num_of_likes": null,
"quote_id": 1
}
]
}
]
注意第三个引用'宾语。它包含'评论3'。注释3的quote_id为1,quote_id是一个外键,它应该只与引号1相关,因此它不应该出现在引用对象3中。此外,我的数据库实际上包含多个注释这些引用,但我的json只返回一条评论,它甚至没有正确引用。
这是我的架构:
BEGIN;
DROP TABLE IF EXISTS quotes;
DROP TABLE IF EXISTS comments;
CREATE TABLE quotes (
id SERIAL PRIMARY KEY,
name VARCHAR,
content VARCHAR,
num_of_flags INTEGER
);
CREATE TABLE comments (
id SERIAL PRIMARY KEY,
comment_content VARCHAR,
num_of_likes INTEGER,
quote_id INTEGER
);
ALTER TABLE ONLY comments
ADD CONSTRAINT quotes_id_fkey
FOREIGN KEY (quote_id)
REFERENCES quotes(id);
COMMIT;
我查看了这个blog,并学习了一些关于json_agg聚合函数的知识,并且能够将一个psql调用拼凑在一起,这确实会使我的评论变为“#”。到一个数组(你可以在我的第二个代码块中看到)。这是psql调用:
SELECT
q.id,
q.content,
q.name,
q.num_of_flags,
json_agg(c.*) as comments
FROM quotes q
INNER JOIN comments c USING (id)
GROUP BY q.id, q.content, q.name, q.num_of_flags
我认为关键是调整psql调用,但我似乎无法做出正确的调整。我还试图应用横向连接,以及我在this Stack Overflow帖子中找到的array_to_json方法,但是还没有能够将它们应用到我的项目中,可能是因为我的语法。
希望这篇文章清晰易懂!我非常感谢你的时间,如果碰巧碰到它并能帮助我。
-Bill
答案 0 :(得分:1)
以错误引号结尾的评论问题是因为您链接USING (id)
上的表格;相反,你应该使用ON quote.id = comment.quote_id
。这可能也导致每个引用只显示一条评论,即使可能有多个或没有。
将行转换为JSON对象的最佳方法是使用json_build_object()
( PG9.4 + )。 json_agg()
将多个JSON对象组合成一个JSON数组。放在一起,你得到这个:
SELECT json_agg(quote_comments) AS json_object
FROM (
SELECT json_build_object('id', q.id,
'name', q.name,
'content', q.content,
'num_of_flags', q.num_of_flags,
'comments', json_agg(c.j)) AS quote_comments
FROM quotes q
LEFT JOIN (
SELECT quote_id, json_build_object('id', id,
'comment_content', comment_content,
'num_of_likes', num_of_likes,
'quote_id', quote_id) AS j
FROM comments) c ON c.quote_id = q.id
GROUP BY 1, 2, 3, 4) sub;
JSON对其对象使用层次结构,您的查询应使用相同的层次结构构建;你可以使用子查询来做到这一点。在每个级别,您都构建一个JSON对象,并根据需要聚合到JSON数组中。由于您有两个级别的聚合,因此您无需在单个(子)查询中对不同的集合进行分组,因此您需要更高级别的子查询。
答案 1 :(得分:0)
Postgres 9.3版对JSON数据类型有很好的支持。 你可以试试这个:
select q.*, row_to_json(c.*) as comments from quotes q inner join comments c using(quote_id);
编辑后使用左连接: 选择q。,row_to_json(c。)作为引号的注释q left join comments c ON q.id = c.quote_id;