如何以json格式

时间:2016-12-12 01:33:28

标签: json postgresql multidimensional-array

我将从顶部开始......我有两张桌子,引号和评论。一句话有很多'评论。我的最终目标是在前端有两个.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

2 个答案:

答案 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;