【问题标题】:Postgres: Getting json object from arrayPostgres:从数组中获取 json 对象
【发布时间】:2020-03-07 10:06:45
【问题描述】:

我想返回 {id: 'single-entry'} 而不是 [{Id:'single-entry'}]

我正在运行PostgreSQL v11.5

我在网上看了很多不同的例子,但是只有一行的数组不会变成json对象。

从这个查询:

SELECT row_to_json(row)
FROM
(
    SELECT 
        t.*,
        json_agg(json_build_object('name', tr."name", 'id', r."remixTrackId")) 
        FILTER (WHERE tr."id" IS NOT NULL)
        AS remixes
    FROM "Tracks" t
        LEFT JOIN "Remixes" r ON r."originalTrackId" = t."id"
        LEFT JOIN "Tracks" tr ON tr."id" = r."remixTrackId"
    WHERE t."id" = '${trackId}'
    GROUP BY t."id"
) row;

我的期望:

{
  "id": "track-id2",
  "name": "My track 2",
  "dateModified": "2019-11-09T21:41:30.482634",
  "channels": {
    "some": "json"
  },
  "userId": 1,
  "remixes": null
}

我得到了什么:

[
  {
    "row_to_json": {
      "id": "track-id2",
      "name": "My track 2",
      "dateModified": "2019-11-09T21:41:30.482634",
      "channels": {
        "some": "json"
      },
      "userId": 1,
      "remixes": null
    }
  }
]

数据库连接和查询如下所示。 我正在使用运行 Postgres 的 Node 和 Heroku

这是我如何执行查询的更完整的 sn-p:

const pg = require('pg')
const config = {
    user: 'xxx',
    database: 'xxx',
    password: 'xxx',
    port: 5432,
    ssl: true
};
const pool = new pg.Pool({ 
    connectionString: `postgres://${config.user}:${config.password}@xxx.amazonaws.com:5432/${config.database}`,
    ...config
})

app.get('/api/postgres/get-track', function(request, response) {
    const trackId = R.path(['query','id'], request)
    pool.connect(function(err, client, done) {
        if(err) {
            response.send("Could not connect to DB: " + err)
        } else {
            client.query(`
            SELECT row_to_json(row)
            FROM
            (
                SELECT 
                    t.*,
                    json_agg(json_build_object('name', tr."name", 'id', r."remixTrackId")) 
                    FILTER (WHERE tr."id" IS NOT NULL)
                    AS remixes
                FROM "Tracks" t
                    LEFT JOIN "Remixes" r ON r."originalTrackId" = t."id"
                    LEFT JOIN "Tracks" tr ON tr."id" = r."remixTrackId"
                WHERE t."id" = '${trackId}'
                GROUP BY t."id"
            ) row;
            `, function(err, result) {
                done()
                if(err) return response.send(err)
                response.send(result.rows);
            })
        }
    }) 
})

请帮我指出我做错了什么。 提前致谢!

【问题讨论】:

  • 如果你不想要数组,为什么要使用json_agg
  • @Bergi 我用它来为“remixes”字段创建一个数组,这是必需的。问题是整个条目最终都在一个数组中。如果我删除 json_agg 和整个“混音”字段,那么它仍然是一个数组。碰巧我查询的这个特定 ID 没有任何混音,然后我返回 null 而不是数组。它也可能是这样的:
  • 啊,现在我看到了你的问题。外部数组由您的数据库驱动程序创建,它不知道查询只返回一个结果 - 它可能包含多行。类似地,它使用 row_to_json 键而不是普通的结果对象输出对象,因为它不知道只有一列 - 可能还有其他列。请向我们展示执行此查询的代码。
  • 跟进我的评论,如果条目有混音,它可能看起来像这样:json [ { "row_to_json":{ "id":"track-id", "name":"My track 1", "dateModified":"2019-11-09T21:41:30.379751", "channels":{ "some":"json" }, "userId":1, "remixes":[ { "name":"My track 2", "id":"track-id2" }, { "name":"My track 3", "id":"track-id3" } ] } } ]
  • 很高兴你解决了,但请post the answer as an answer

标签: javascript node.js json postgresql node-postgres


【解决方案1】:

您可以删除json_agg()函数并将SELECT列表中的所有列添加到子查询中的GROUP BY列表中

SELECT row_to_json(row) as remixes
  FROM
  (
    SELECT 
          t."id", t."name", t."dateModified",
          json_build_object('some', tr."some") AS channels,
          t."userId", null AS "remixes"
      FROM "Tracks" t
      LEFT JOIN "Remixes" r ON r."originalTrackId" = t."id"
      LEFT JOIN "Tracks" tr ON tr."id" = r."remixTrackId"
     WHERE t."id" = '${trackId}'
  GROUP BY t."id", t."name", t."userId", tr."some", t."dateModified"
) row  

【讨论】:

    【解决方案2】:

    我解决了,解决方案是这样的(在JS的帮助下):

    const R = require('ramda')
    const pg = require('pg')
    
    app.get('/api/postgres/get-track', function(request, response) {
        const trackId = R.path(['query','id'], request)
        pool.connect(function(err, client, done) {
            if(err) {
                response.send("Could not connect to DB: " + err)
            } else {
                client.query(`
                    SELECT 
                        t.*,
                        json_agg(json_build_object('name', tr."name", 'id', r."remixTrackId")) 
                        FILTER (WHERE tr."id" IS NOT NULL)
                        AS remixes
                    FROM "Tracks" t
                        LEFT JOIN "Remixes" r ON r."originalTrackId" = t."id"
                        LEFT JOIN "Tracks" tr ON tr."id" = r."remixTrackId"
                    WHERE t."id" = '${trackId}'
                    GROUP BY t."id";
                `, function(err, result) {
                    done()
                    if(err) return response.send(err)
                    const foundTrack = R.head(result.rows)
                    if(foundTrack) {
                        response.send(foundTrack)
                    } else {
                        //Error response here
                    }
                })
            }
        }) 
    })
    

    【讨论】:

      猜你喜欢
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 1970-01-01
      相关资源
      最近更新 更多