Postgres 9.5 - 查询嵌套 JSON 元素的数组长度

Posted

技术标签:

【中文标题】Postgres 9.5 - 查询嵌套 JSON 元素的数组长度【英文标题】:Postgres 9.5 - Querying array length of a nested JSON element 【发布时间】:2017-04-26 10:23:07 【问题描述】:

我有一个包含 JSON 字段的 Postgres 表,该字段标识与给定记录关联的图像。该字段的内容如下所示:

 "photo-verification": 
   "photos": [
     "type": "photo-verification", "fileName": "4f35a880-e9a0-43f9-a31e-1bb8b765d04d", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T20:25:39.706Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T20:25:39.706Z",
     "type": "photo-verification", "fileName": "3a104d07-dc48-4f59-b83f-06cd35a21dae", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T22:31:09.808Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T22:31:09.808Z"
     ]
   

一条记录可以有 0 个或多个关联图像 - 如果没有图像,则整个字段将为空。我正在尝试编写一个查询来确定与给定记录关联的图像数量。最终结果应该是计算有多少条记录有一张图像,有多少条记录有不止一张。如果我查询 JSON 的顶层,如下所示:

select n.images->'photo-verification' from notes n;

我可以获得包含照片数组的内部 JSON,但如果我尝试更深入地挖掘,我不会得到任何结果。我的想法是我可以做一些类似的事情

select array_length(n.images->'photo-verification'->'photos', 1) from notes n;

select json_array_length(n.images->'photo-verification'->'photos') from notes n;

但我最终得到了错误和提示,也许我应该考虑强制转换。

我刚刚开始深入研究 Postgres,所以我仍在尝试围绕查询语言的一些更精细的点展开思考。我将继续研究,但如果有人提供任何帮助或见解,我将不胜感激。

编辑:

所以,我认为我可以通过创建一个仅包含“照片”JSON 并过滤掉所有空字段的视图来简化问题:

CREATE VIEW photos as SELECT n.images->'photo-verification' as photo FROM notes.notes n where (n.images->'photo-verification')::text != '';

它起作用了,因为我现在有一个带有 JSON 列的视图,如下所示:

   "photos": [
     "type": "photo-verification", "fileName": "4f35a880-e9a0-43f9-a31e-1bb8b765d04d", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T20:25:39.706Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T20:25:39.706Z",
     "type": "photo-verification", "fileName": "3a104d07-dc48-4f59-b83f-06cd35a21dae", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T22:31:09.808Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T22:31:09.808Z"
     ]
   

但是,如果我尝试

select json_array_length(photo) from photos;

我明白了:

ERROR: cannot get array length of a scalar

如果我尝试

select json_array_length(photo->'photos') from photos;

我得到一堆空白记录。

我一定是错过了什么……

【问题讨论】:

【参考方案1】:
create temp table t (id int, data json);
insert into t values 
(1, 
'"photo-verification": 
   "photos": [
     "type": "photo-verification", "fileName": "4f35a880-e9a0-43f9-a31e-1bb8b765d04d", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T20:25:39.706Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T20:25:39.706Z",
     "type": "photo-verification", "fileName": "3a104d07-dc48-4f59-b83f-06cd35a21dae", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T22:31:09.808Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T22:31:09.808Z"
     ]
   
'),
(2, 
'"photo-verification": 
   "photos": [
     "type": "photo-verification", "fileName": "4f35a880-e9a0-43f9-a31e-1bb8b765d04d", "mimeType": "image/jpeg", "createdBy": "jmlittm", "createdTs": "2016-06-20T20:25:39.706Z", "delFlag": false, "updatedBy": "jmlittm", "updatedTs": "2016-06-20T20:25:39.706Z"
     ]
   
')
;

select id, json_array_length(data->'photo-verification'->'photos')
from t;

或者,如果您对某个特定领域感兴趣:

select json_array_elements(data->'photo-verification'->'photos')->>'fileName' as fileName
from t;

【讨论】:

谢谢,mcNets - 这正是我正在寻找的。有趣的是,如果我直接从表中运行该查询 - select id, json_array_length(images->'photo-verification'->'photos') from notes.notes where images::text != '';,我会得到所有的 ID,但长度字段是空的。我正在使用外部数据包装器,但数据通过时看起来仍然没问题。也许如果我做了一个 SELECT INTO,并将它放在一个临时表中,我可能会有更好的运气。 【参考方案2】:

似乎需要转换为 JSON:

select json_array_length((images->'photo-verification'->'photos')::json)
from notes;

【讨论】:

好吧,我尝试了select count(*) from notes where json_array_length((images->'photo-verification'->'photos')::json) > 1;,结果返回计数为零。不过,这似乎是正确的轨道。感谢收看!

以上是关于Postgres 9.5 - 查询嵌套 JSON 元素的数组长度的主要内容,如果未能解决你的问题,请参考以下文章

在postgres 9.5中插入包含json对象的数组作为行

Postgres:使用 django 对 json 键进行值查询

嵌套json的查询

RDS postgres 从 9.4 升级到 9.5,CPU 卡在 100% 几个小时

查询嵌套 JSON 数组 PostgreSQL 中的所有元素

将 json 转换为嵌套的 postgres 复合类型