Postgres Json(b)int数组包含任何数组值

时间:2018-01-18 12:29:37

标签: sql json postgresql jsonb

TLDR:如何查找包含json数组的每条记录,其中包含一个给定数组/列表的数字。

好的,我尝试了很多,阅读了很多其他的Threads,但我还没有找到合适的解决方案。我想在Postgres中找到一些JSON对象。它们包含多项选择的索引。

物件:

[{"id": 5, "list": [1, 2, 3]}, {"id": 6, "list": [4, 5, 6]}]

我需要选择包含Items 1 OR 5的所有对象。现在,我只能检查一个值

SELECT '[1, 2, 3, 4]'::jsonb @> '3'::jsonb as result;

或两者都存在:

SELECT '[1,2,3,4]'::jsonb @> '[1, 2]'::jsonb as result;

或者,有趣的是,如果我有一个字符串数组,我可以做我需要的东西:

SELECT '["1","2","3","4"]'::jsonb ?| array['1', '5'] as result;

如何将此应用于JSON数字数组?我尝试了转换为int []和其他很多东西。没有任何效果。我需要将数字数组转换为文本数组以使用它或找到右侧的正确的转换。这也不起作用:?| array[1, 5]::text[]

解决方案1:

嗯,使用OR时,我和毛泽恩心中的第一件事看起来仍然是最快最简单的解决方案。

解决方案2:

我终于找到了一种方法来缩短它(就像我认为它应该工作一样)但它是一个强大的地狱(也是9.4+)并且看起来并不漂亮:

SELECT array_to_json(translate('[1,2,3,4]'::jsonb::text, '[]', '{}')::text[])::jsonb ?| array['1','5'] as result;

这基本上将整数转换为字符串。

3 个答案:

答案 0 :(得分:5)

您可以使用OR

t=# SELECT '[1, 2, 3, 4]'::jsonb @> '3'::jsonb OR '[1, 2, 3, 4]'::jsonb @> '5'::jsonb as result;
 result
--------
 t
(1 row)

或将unnested jsonb数组聚合到int数组,以便在它相交时进行比较:

t=# with c(j) as (values('[1, 2, 3, 4]'::jsonb))
, a as (select j,jsonb_array_elements(j) ja from c)
select array_agg(ja), j, array_agg(ja::text::int) && array[5,4] from a group by j;
 array_agg |      j       | ?column?
-----------+--------------+----------
 {1,2,3,4} | [1, 2, 3, 4] | t
(1 row)
您的示例中的

because all jsonb operators behave as documented。而且我没有看到一些优雅的简短解决方案......

答案 1 :(得分:0)

您可以使用jsonb_array_elements,强制转换为文本,然后使用int并与array_agg结合使用。

WITH j AS (SELECT array_agg(h), othercol, thirdcol a FROM
  (SELECT jsonb_array_elements('[53,22,41,23]')::text::int h, othercol,
    thirdcol) AS j GROUP BY othercol, thirdcol)
SELECT othercol, thirdcol FROM j WHERE j.a && ARRAY[44,13,12,41];

不完全优雅,尤其是当您考虑group by语句

答案 2 :(得分:0)

您也可以这样做:

select translate('[1,2,3]', '[]','{}')::int[] && ARRAY[1,3]