在 postgresql 中,如何 select jsonb 数组包含对象的行?

In postgresql how can I select rows where a jsonb array contains objects?

我的数据库 table 是这样的(数据是一个 JSONB 列):

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

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

假设:

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 应该给出您预期的结果

在未嵌套的 json 数组上使用带有过滤器的 where 将 return id 为 1、2 和 3 的行

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

jsonb_array_elements 会损害性能。如果这是一个问题,您可以改用此查询

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