postgresql Postgres从jsonb数组中获取值匹配的所有元素

xxb16uws  于 12个月前  发布在  PostgreSQL
关注(0)|答案(2)|浏览(303)

我想我正在尝试一些简单的东西,但几个小时后我就是不能让它工作。我有一个包含tags列的表,它是一个jsonb数组,看起来像这样:

[
    {
        "name": "e-commerce",
        "weight": 400
    },
    {
        "name": "management",
        "weight": 200
    },
    {
        "name": "content management",
        "weight": 200
    }
]

字符串
现在我想写一个查询,当名称与搜索字符串匹配时,它会返回完整的对象。到目前为止,我想到了这个:

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线程的解决方案,但无济于事:-(

lndjwyie

lndjwyie1#

如果你想让每个匹配的对象在单独的一行上,你可以使用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'
)

ioekq8ef

ioekq8ef2#

您需要查询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'

编辑一:

由于您的数据类型不是jsonb而是jsonb[],因此需要使用unnest将其解嵌套为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在该上下文中不可用

相关问题