在Postgres中查询对象的JSON数组

时间:2018-07-10 00:21:11

标签: json postgresql

我有一个带json数据字段的postgres数据库。 我拥有的json是一个对象数组:

[{"name":"Mickey Mouse","age":10},{"name":"Donald Duck","age":5}]

我试图返回JSON数组中特定键的值,因此在上面的示例中,我想返回name的值。

当我使用以下查询时,我只会得到一个NULL值:

SELECT data->'name' AS name FROM json_test

我是否认为这是因为它是对象数组?可以直接输入姓名键吗?

最终我需要做的是返回每个唯一名称的计数,这可能吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以使用jsonb_array_elements (when using jsonb) or json_array_elements (when using json)扩展数组元素。

例如:

WITH sample_data_array(arr) AS (
    VALUES ('[{"name":"Mickey Mouse","age":10},{"name":"Donald Duck","age":5}]'::jsonb)
)
, sample_data_elements(elem) AS (
    SELECT jsonb_array_elements(arr) FROM sample_data_array
)
SELECT elem->'name' AS extracted_name FROM sample_data_elements;

在此示例中,sample_data_elements等效于具有一个名为jsonb的单个elem列且具有两行(初始数据中的两个数组元素)的表。

结果由两行组成(一个jsonb列,或者如果您使用text则为->>'name'类型):

 extracted_name
----------------
 "Mickey Mouse"
 "Donald Duck"
(2 rows)

您应该让他们能够照常进行分组和汇总,以返回单个名称的计数。

答案 1 :(得分:1)

首先必须使用函数(json_array_elements jsonb_array_elements(如果您具有jsonb数据类型)来取消 json对象的数组,则可以通过指定键来访问值。

WITH json_test (col) AS (
  values (json '[{"name":"Mickey Mouse","age":10},{"name":"Donald Duck","age":5}]')
)
SELECT
  y.x->'name' "name"
FROM json_test jt, 
LATERAL (SELECT json_array_elements(jt.col) x) y

-- outputs:
name
--------------
"Mickey Mouse"
"Donald Duck"

要获得唯一名称的计数,它与上面的查询类似,只是对y.x->>name应用计数独特的聚合函数

WITH json_test (col) AS (
  values (json '[{"name":"Mickey Mouse","age":10},{"name":"Donald Duck","age":5}]')
)
SELECT
  COUNT( DISTINCT y.x->>'name') distinct_names
FROM json_test jt, 
LATERAL (SELECT json_array_elements(jt.col) x) y

有必要使用->>代替->,因为前者(->>)将提取的值强制转换为文本,从而支持相等比较(需要不同的计数),而后者(->)将值提取为json,不支持相等比较。

或者,将json转换为jsonb并使用jsonb_array_elementsJSONB支持相等比较,因此可以使用COUNT DISTINCT以及通过->提取,即

COUNT(DISTINCT (y.x::jsonb)->'name')

答案 2 :(得分:1)

这样做:

SELECT * FROM json_test WHERE (column_name @> '[{"name": "Mickey Mouse"}]');