繁体   English   中英

在 Postgres 中查询 JSON 对象数组

[英]Querying a JSON array of objects in Postgres

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

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

我正在尝试返回 JSON 数组中特定键的值,因此在上面的示例中,我想返回名称的值。

当我使用以下查询时,我只返回一个 NULL 值:

SELECT data->'name' AS name FROM json_test

我假设这是因为它是一个对象数组? 是否可以直接寻址名称键?

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

谢谢!

您必须首先使用函数(如果您有jsonb数据jsonb_array_elements ,则为json_array_elements或 jsonb_array_elements )取消嵌套 json-objects 数组,然后您可以通过指定键来访问这些值。

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"

要获得唯一名称的计数,它与上面的查询类似,除了 count distinct 聚合函数应用于yx->>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_elements JSONB支持相等比较,因此可以使用 COUNT DISTINCT 以及通过->提取,即

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

postgresql 版本 12+ 的更新答案

现在可以使用 jsonb 路径查询从对象列表中提取/取消嵌套特定键,只要查询的字段是 jsonb 而不是 json。

例子:

WITH json_test (col) AS (
  values (jsonb '[{"name":"Mickey Mouse","age":10},{"name":"Donald Duck","age":5}]')
)
SELECT jsonb_path_query(col, '$[*].name') "name"
FROM json_test
-- replaces this original snippet:
-- SELECT
--   y.x->'name' "name"
-- FROM json_test jt, 
-- LATERAL (SELECT json_array_elements(jt.col) x) y

您可以使用jsonb_array_elements (使用jsonb时)或json_array_elements (使用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等效于具有单个名为elemjsonb列的表,该表具有两行(初始数据中的两个数组元素)。

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

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

您应该能够像往常一样对它们进行分组和聚合以返回单个名称的计数。

这样做:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM