在PostgreSQL中,我如何选择jsonb数组包含对象的行?

时间:2018-07-10 13:55:25

标签: postgresql jsonb

我的数据库表是这样的(数据是JSONB列):

 id |                 data                 
----+--------------------------------------
  1 | {"tags": [{"name": "tag1"}, {"name": "tag2"}]}
  2 | {"tags": [{"name": "tag2"}]}
  3 | {"tags": [{"name": "tag3"}]}
  4 | {"tags": [{"name": "tag4"}]}

我想编写一个查询,该查询将返回其中data包含标签tag2tag3的行。因此,应该返回第1、2和3行。 我一直在看PostgreSQL JSONB文档,但我不清楚如何查询这样的嵌套结构。我将如何编写where子句?

3 个答案:

答案 0 :(得分:1)

在未嵌套的json数组上使用过滤器存在的地方将返回ID为1、2和3的行

SELECT * 
FROM mytable
WHERE EXISTS (
    SELECT TRUE 
    FROM jsonb_array_elements(data->'tags') x 
    WHERE x->>'name' IN ('tag2', 'tag3')
)

答案 1 :(得分:0)

比方说:

db=# create table so33(id int, data jsonb);
CREATE TABLE
db=# copy so33 from stdin delimiter '|';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>>   1 | {"tags": [{"name": "tag1"}, {"name": "tag2"}]}
  2 | {"tags": [{"name": "tag2"}]}
  3 | {"tags": [{"name": "tag3"}]}
  4 | {"tags": [{"name": "tag4"}]}>> >> >>
>> \.
COPY 4

then

db=# with c as (select *,jsonb_array_elements(data->'tags')->>'name' e from so33)
select * from c where e in ('tag2','tag3');
 id |                      data                      |  e
----+------------------------------------------------+------
  1 | {"tags": [{"name": "tag1"}, {"name": "tag2"}]} | tag2
  2 | {"tags": [{"name": "tag2"}]}                   | tag2
  3 | {"tags": [{"name": "tag3"}]}                   | tag3
(3 rows)

应该做一个简单的jsonb_array_elements

显然SELECT DISTINCT id, data FROM e应该能提供您期望的结果

答案 2 :(得分:0)

jsonb_array_elements会损害性能。如果您对此有疑问,可以改用此查询

SELECT * FROM MyTable where 
    data @> '[{"name": "tag2"}]'::jsonb 
    or 
    data @> '[{"name": "tag3"}]'::jsonb;