尝试在 Postgresql 9.3 中查询 JSON 非对象数组
Trying to query a JSON array of non-objects in Postgresql 9.3
我正在尝试使用 JSON 列查询 table,该列将始终保存 "primitive" 值的数组(即整数、字符串、布尔值——不是对象或数组)。
我的查询应该类似于 [ref2],但我不能 ->>'id'
因为我不是要访问 JSON 对象而是访问值本身。
在 [ref1] fiddle(上面的明显分支)中,有不完整的查询... 我想查询所有 things
包含 3
在其值中 .
更重要的是,我希望某些行具有字符串数组,其他行具有整数数组,而其他行具有布尔数组...所以转换是不可取的。
我相信->>
returns原来的JSON值类型,但是我需要"root"对象...也就是我的JSON值是 [1,2,3,4]
,使用 json_array_elements
应该产生例如2
,但根据我的测试,这是 JSON 类型。
计划在不久的将来升级到 9.4,但我还没有读到任何给我线索的东西 jsonb
会对我有所帮助。
更新:目前,我 (1) 确保所有值都是整数(将非整数值映射到整数),这是次优的; (2) 像这样查询:
SELECT *
FROM things, json_array_elements(things.values) AS vals
WHERE vals.value::text::integer IN (1,2,3);
我需要双重铸造(否则它会抱怨 cannot cast type json to integer
)。
ref1: http://sqlfiddle.com/#!15/5febb/1
ref2: How to query an array of JSON in PostgreSQL 9.3?
您可以使用 generate_series
解压数组,而不是使用 json_array_elements
,使用 ->>
运算符提取文本表示。
SELECT things.*
FROM things
CROSS JOIN generate_series(0, json_array_length(values) - 1) AS idx
WHERE values ->> idx = '1'
GROUP BY things.id;
这是针对 9.3 中缺少 json_array_elements_text
的解决方法。
您需要一个 operator(=)
用于 json 来执行此操作,而不会混淆转换或依赖整数、布尔值等的特定文本表示。operator(=)
仅适用于jsonb
。因此,在 9.3 中,您只能使用文本表示(因此 1.00
不会 =
1
)或基于元素类型转换为 PostgreSQL 类型。
在 9.4 中,您可以使用 to_json
和 jsonb operator(=)
,例如:
SELECT things.*
FROM things
CROSS JOIN generate_series(0, json_array_length(values) - 1) AS idx
WHERE (values -> idx)::jsonb = to_json(1)::jsonb
GROUP BY things.id;
id | date | values
----+-------------------------------+---------
1 | 2015-08-09 04:54:38.541989+08 | [1,2,3]
(1 row)
我正在尝试使用 JSON 列查询 table,该列将始终保存 "primitive" 值的数组(即整数、字符串、布尔值——不是对象或数组)。
我的查询应该类似于 [ref2],但我不能 ->>'id'
因为我不是要访问 JSON 对象而是访问值本身。
在 [ref1] fiddle(上面的明显分支)中,有不完整的查询... 我想查询所有 things
包含 3
在其值中 .
更重要的是,我希望某些行具有字符串数组,其他行具有整数数组,而其他行具有布尔数组...所以转换是不可取的。
我相信->>
returns原来的JSON值类型,但是我需要"root"对象...也就是我的JSON值是 [1,2,3,4]
,使用 json_array_elements
应该产生例如2
,但根据我的测试,这是 JSON 类型。
计划在不久的将来升级到 9.4,但我还没有读到任何给我线索的东西 jsonb
会对我有所帮助。
更新:目前,我 (1) 确保所有值都是整数(将非整数值映射到整数),这是次优的; (2) 像这样查询:
SELECT *
FROM things, json_array_elements(things.values) AS vals
WHERE vals.value::text::integer IN (1,2,3);
我需要双重铸造(否则它会抱怨 cannot cast type json to integer
)。
ref1: http://sqlfiddle.com/#!15/5febb/1
ref2: How to query an array of JSON in PostgreSQL 9.3?
您可以使用 generate_series
解压数组,而不是使用 json_array_elements
,使用 ->>
运算符提取文本表示。
SELECT things.*
FROM things
CROSS JOIN generate_series(0, json_array_length(values) - 1) AS idx
WHERE values ->> idx = '1'
GROUP BY things.id;
这是针对 9.3 中缺少 json_array_elements_text
的解决方法。
您需要一个 operator(=)
用于 json 来执行此操作,而不会混淆转换或依赖整数、布尔值等的特定文本表示。operator(=)
仅适用于jsonb
。因此,在 9.3 中,您只能使用文本表示(因此 1.00
不会 =
1
)或基于元素类型转换为 PostgreSQL 类型。
在 9.4 中,您可以使用 to_json
和 jsonb operator(=)
,例如:
SELECT things.*
FROM things
CROSS JOIN generate_series(0, json_array_length(values) - 1) AS idx
WHERE (values -> idx)::jsonb = to_json(1)::jsonb
GROUP BY things.id;
id | date | values
----+-------------------------------+---------
1 | 2015-08-09 04:54:38.541989+08 | [1,2,3]
(1 row)