尝试在 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)