Postgres 从 jsonb 数组中获取值匹配的所有元素
Postgres get all elements where value matches from jsonb array
我想我正在尝试一些简单的事情,但几个小时后我就是无法让它工作。我有一个 table,其中包含一个 tags 列,它是一个 jsonb 数组,如下所示:
{"{\"name\": \"e-commerce\", \"weight\": 400}","{\"name\": \"management\", \"weight\": 200}","{\"name\": \"content management\", \"weight\": 200}"}
我现在想写一个 returns 完整对象的查询,当名称与搜索字符串匹配时。到目前为止,我想到了这个:
SELECT * FROM data
WHERE tags is not null
AND EXISTS(
SELECT FROM data ad WHERE (ad.tags -> 'name' ->> 'education')::text
);
但是我得到这个错误:
[42883] ERROR: operator does not exist: jsonb[] -> unknown Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
我不确定我应该在哪里进行类型转换以及这是否真的是问题所在。
我已经尝试了 these threads 的解决方案,但无济于事:-(
您需要查询json array
内的对象。使用 jsonb_array_elements
创建这些对象,然后像 -
一样查询 json
SELECT d.* FROM data d, jsonb_array_elements(d.tags) tag
WHERE tag is not null and WHERE (tag -> 'name') ? 'education'
此外,在您的原始查询中添加注释
这个-
WHERE (ad.tags -> 'name' ->> 'education')::text
应该是-
WHERE (ad.tags -> 'name') ? 'education'
或
WHERE (ad.tags ->> 'name')::text = 'education'
编辑 1:
由于您的数据类型不是 jsonb 而是 jsonb[],您需要使用 unnest
-[=20= 将其取消嵌套到 jsonb ]
SELECT * FROM data d, jsonb_array_elements(unnest(d.tags)) tagObj
WHERE tagObj is not null and WHERE (tag -> 'name') ? 'education'
或
select * from (
SELECT * FROM data d, jsonb_array_elements(unnest(d.tags)) tagobj
) a WHERE tag is not null and WHERE (tag -> 'name') ? 'education'
第一个可能会出错,因为 tagObj
在那个上下文中不可用
如果您希望每个匹配的对象在单独的行中,您可以使用jsonb_array_elements()
取消对象数组的嵌套,然后过滤:
select o.obj
from data d
cross join lateral jsonb_array_elements(d.tags) o(obj)
where o.obj ->> 'name' = 'education'
这适用于你有 JSONB 数组(所以数据的数据类型是 jsonb
)。
另一方面,如果您有一个 json 对象数组(因此:jsonb[]
),您可以 unnest
代替:
select o.obj
from data d
cross join lateral unnest(d.tags) o(obj)
where o.obj ->> 'name' = 'education'
请注意,当两个对象在同一数组中匹配时,这会生成两行。如果你只想要一行,你可以使用 exists
代替:
select o.obj
from data d
where exists (
select 1 from unnest(d.tags) o(obj) where o.obj ->> 'name' = 'education'
)
我想我正在尝试一些简单的事情,但几个小时后我就是无法让它工作。我有一个 table,其中包含一个 tags 列,它是一个 jsonb 数组,如下所示:
{"{\"name\": \"e-commerce\", \"weight\": 400}","{\"name\": \"management\", \"weight\": 200}","{\"name\": \"content management\", \"weight\": 200}"}
我现在想写一个 returns 完整对象的查询,当名称与搜索字符串匹配时。到目前为止,我想到了这个:
SELECT * FROM data
WHERE tags is not null
AND EXISTS(
SELECT FROM data ad WHERE (ad.tags -> 'name' ->> 'education')::text
);
但是我得到这个错误:
[42883] ERROR: operator does not exist: jsonb[] -> unknown Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
我不确定我应该在哪里进行类型转换以及这是否真的是问题所在。
我已经尝试了 these threads 的解决方案,但无济于事:-(
您需要查询json array
内的对象。使用 jsonb_array_elements
创建这些对象,然后像 -
SELECT d.* FROM data d, jsonb_array_elements(d.tags) tag
WHERE tag is not null and WHERE (tag -> 'name') ? 'education'
此外,在您的原始查询中添加注释
这个-
WHERE (ad.tags -> 'name' ->> 'education')::text
应该是-
WHERE (ad.tags -> 'name') ? 'education'
或
WHERE (ad.tags ->> 'name')::text = 'education'
编辑 1:
由于您的数据类型不是 jsonb 而是 jsonb[],您需要使用 unnest
-[=20= 将其取消嵌套到 jsonb ]
SELECT * FROM data d, jsonb_array_elements(unnest(d.tags)) tagObj
WHERE tagObj is not null and WHERE (tag -> 'name') ? 'education'
或
select * from (
SELECT * FROM data d, jsonb_array_elements(unnest(d.tags)) tagobj
) a WHERE tag is not null and WHERE (tag -> 'name') ? 'education'
第一个可能会出错,因为 tagObj
在那个上下文中不可用
如果您希望每个匹配的对象在单独的行中,您可以使用jsonb_array_elements()
取消对象数组的嵌套,然后过滤:
select o.obj
from data d
cross join lateral jsonb_array_elements(d.tags) o(obj)
where o.obj ->> 'name' = 'education'
这适用于你有 JSONB 数组(所以数据的数据类型是 jsonb
)。
另一方面,如果您有一个 json 对象数组(因此:jsonb[]
),您可以 unnest
代替:
select o.obj
from data d
cross join lateral unnest(d.tags) o(obj)
where o.obj ->> 'name' = 'education'
请注意,当两个对象在同一数组中匹配时,这会生成两行。如果你只想要一行,你可以使用 exists
代替:
select o.obj
from data d
where exists (
select 1 from unnest(d.tags) o(obj) where o.obj ->> 'name' = 'education'
)