简体   繁体   English

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

[英]Postgres get all elements where value matches from jsonb array

I think I am trying something simple, but after hours I just can't get it to work.我想我正在尝试一些简单的事情,但几个小时后我就是无法让它工作。 I have a table which contains a tags column, which is a jsonb array and looks like this:我有一个包含标签列的表,它是一个 jsonb 数组,如下所示:

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

I now want to write a query which returns the full object to me, when the name matches the search string.我现在想编写一个查询,当名称与搜索字符串匹配时,它会向我返回完整的 object。 So far I came up with this:到目前为止,我想出了这个:

SELECT * FROM data
WHERE tags is not null
  AND EXISTS(
        SELECT FROM data ad WHERE (ad.tags -> 'name' ->> 'education')::text
    );

But I get this error:但我得到这个错误:

[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.

I am not sure where I should do a typecast and whether that is really the problem.我不确定我应该在哪里进行类型转换,以及这是否真的是问题所在。

I already tried solutions from these threads , but to no avail:-(我已经尝试了这些线程的解决方案,但无济于事:-(

If you want each matching object on a separate row, you can use jsonb_array_elements() to unnest the array of objects, then filter:如果您希望每个匹配的 object 在单独的行上,您可以使用jsonb_array_elements()对象数组,然后过滤:

select o.obj
from data d
cross join lateral jsonb_array_elements(d.tags) o(obj)
where o.obj ->> 'name' = 'education'

That works in you have JSONB array (so the datatype of data is jsonb ).这适用于你有 JSONB 数组(所以数据的数据类型是jsonb )。

If, on the other hand, you have an array of json objects (so: jsonb[] ), you can unnest instead:另一方面,如果您有一个 json 对象数组(例如: unnest jsonb[] ),则可以取消嵌套:

select o.obj
from data d
cross join lateral unnest(d.tags) o(obj)
where o.obj ->> 'name' = 'education'

Note that this generates two rows when two objects match in the same array.请注意,当两个对象在同一个数组中匹配时,这会生成两行。 If you want just one row, you can use exists instead:如果你只想要一行,你可以使用exists代替:

select o.obj
from data d
where exists (
    select 1 from unnest(d.tags) o(obj) where o.obj ->> 'name' = 'education'
)

You need to query the objects within the json array .您需要查询json array中的对象。 Create those objects using jsonb_array_elements and then query the json like -使用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'

Also, a note, in your original query另外,请注意,在您的原始查询中

This -这个 -

WHERE (ad.tags -> 'name' ->> 'education')::text

Should be -应该 -

WHERE (ad.tags -> 'name') ? 'education'

Or或者

WHERE (ad.tags ->> 'name')::text = 'education'

EDIT 1:编辑1:

Since your data type is not jsonb but jsonb[], you need to unnest it to jsonb using unnest -由于您的数据类型不是 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'

Or或者

select * from (
SELECT * FROM data d, jsonb_array_elements(unnest(d.tags)) tagobj
) a WHERE tag is not null and  WHERE (tag -> 'name') ? 'education'

First one may give error, due to tagObj not being available at that context第一个可能会出错,因为tagObj在该上下文中不可用


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM