jsonb_array_elements(2D数组)中的搜索元素

时间:2019-02-19 14:42:45

标签: sql arrays json postgresql jsonb

我有一个带有2列R(id int,dat jsonb)的表。 b列jsonb由2D数组[] []组成。 例如:

id| dat
1 | {"name":"a","numbers":[[1,2],[3,4],[5,6],[1,3]]}
2 | {"age":5,"numbers":[[1,1]]}
3 | {"numbers":[[5,6],[6,7]]}

我正在尝试在这些子数组之一中查找包含特定数字的所有ID。 我使用了2个解决方案,我想了解为什么第一个不起作用:

1)

select * from R 
where exists (
    select from jsonb_array_elements(R.dat->'numbers')->>0 first,jsonb_array_elements(range.data->'numbers')->>1 second where first::decimal= 1 and second::decimal= 1
);
ERROR:  syntax error at or near "->>"
LINE 3: ...t from jsonb_array_elements(R.dat->'numbers')->>0 first,j...

2)

SELECT *
FROM  R 
WHERE  EXISTS (
   SELECT FROM jsonb_array_elements(R.dat-> 'numbers') subarray
   WHERE (subarray->>0)::decimal = 1 and (subarray->>1)::decimal = 1
   );

此外,我看到gin索引不处理此运算符,因此基本上任何索引都可以在这里帮忙吗?

1 个答案:

答案 0 :(得分:0)

您的第一个查询会引发错误,因为您只能在FROM子句中使用Find all the members of a group(不能使用值表达式)。

您可以使第二个查询更简单:

select *
from  r
where exists (
    select from jsonb_array_elements(dat->'numbers') subarray
    where subarray = '[1,1]'
    );

或在横向连接中使用该功能:

select r.*
from r
cross join jsonb_array_elements(dat->'numbers')
where value = '[1,1]';

由于使用了jsonb_array_elements(),因此没有索引可以支持这些查询。

您可能会想像这样使用遏制运算符@>

select *
from r
where dat->'numbers' @> '[[1,1]]'::jsonb

 id |                            dat                             
----+------------------------------------------------------------
  1 | {"name": "a", "numbers": [[1, 2], [3, 4], [5, 6], [1, 3]]}
  2 | {"age": 5, "numbers": [[1, 1]]}
(2 rows)

很不幸,如您所见,它无法按预期工作。在数组上使用运算符有点棘手,因为它的工作方式如下:array1 @> array2为真,如果j的每个元素array2都有一个i array1中的“ i @> j”。因此,根据table experssions

  

进行容纳匹配时,数组元素的顺序并不重要,重复数组元素仅被有效考虑一次。