在 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
包含标签 tag2
或 tag3
的行。因此第 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;
我的数据库 table 是这样的(数据是一个 JSONB 列):
id | data
----+--------------------------------------
1 | {"tags": [{"name": "tag1"}, {"name": "tag2"}]}
2 | {"tags": [{"name": "tag2"}]}
3 | {"tags": [{"name": "tag3"}]}
4 | {"tags": [{"name": "tag4"}]}
我想编写一个查询,该查询将 return data
包含标签 tag2
或 tag3
的行。因此第 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;