Sql JSONB数组包含like OR和and运算符
考虑一个表Sql JSONB数组包含like OR和and运算符,sql,json,postgresql,jsonb,Sql,Json,Postgresql,Jsonb,考虑一个表temp(jsondatajsonb) Postgres提供了一种使用 SELECT jsondata FROM temp WHERE (jsondata->'properties'->'home') ? 'football' 但是,我们不能对数组包含使用LIKE运算符。在数组中获得LIKE的一种方法是使用- SELECT jsondata FROM temp,jsonb_array_elements_text(temp.jsondata->'properti
temp(jsondatajsonb)
Postgres提供了一种使用
SELECT jsondata
FROM temp
WHERE (jsondata->'properties'->'home') ? 'football'
但是,我们不能对数组包含使用LIKE运算符。在数组中获得LIKE的一种方法是使用-
SELECT jsondata
FROM temp,jsonb_array_elements_text(temp.jsondata->'properties'->'home')
WHERE value like '%foot%'
或类似的操作可以通过使用-
SELECT DISTINCT jsondata
FROM temp,jsonb_array_elements_text(temp.jsondata->'properties'->'home')
WHERE value like '%foot%' OR value like 'stad%'
但是,我无法在JSONB数组中使用LIKE运算符执行和操作 我有以下内容,但有点烦琐。也许有更好的方法,但我认为这是可行的 其思想是找到匹配的JSON数组条目,然后收集结果。在连接条件中,我们检查“matches”数组是否具有预期的条目数
CREATE TABLE temp (jsondata jsonb);
INSERT INTO temp VALUES ('{"properties":{"home":["football","stadium",16]}}');
SELECT jsondata FROM temp t
INNER JOIN LATERAL (
SELECT array_agg(value) AS matches
FROM jsonb_array_elements_text(t.jsondata->'properties'->'home')
WHERE value LIKE '%foo%' OR value LIKE '%sta%'
LIMIT 1
) l ON array_length(matches, 1) = 2;
jsondata
-------------------------------------------------------
{"properties": {"home": ["football", "stadium", 16]}}
(1 row)
使用
jsonb\u array\u elements()
取消对数组的测试后,可以检查满足其中一个条件的值,并按原始行分组求和,例如:
drop table if exists temp;
create table temp(id serial primary key, jsondata jsonb);
insert into temp (jsondata) values
('{"properties":{"home":["football","stadium","16"]}}'),
('{"properties":{"home":["football","player","16"]}}'),
('{"properties":{"home":["soccer","stadium","16"]}}');
select jsondata
from temp
cross join jsonb_array_elements_text(temp.jsondata->'properties'->'home')
group by jsondata
-- or better:
-- group by id
having sum((value like '%foot%' or value like 'stad%')::int) = 2
jsondata
---------------------------------------------------------
{"properties": {"home": ["football", "stadium", "16"]}}
(1 row)
更新。对于大型数据集,上面的查询可能很昂贵。有一个简化但更快的解决方案。您可以将数组强制转换为文本并对其应用like
,例如:
select jsondata
from temp
where jsondata->'properties'->>'home' like all('{%foot%, %stad%}');
jsondata
---------------------------------------------------------
{"properties": {"home": ["football", "stadium", "16"]}}
(1 row)
我将把数组转换成文本。然后,您可以使用每个字符串运算符搜索关键字
缺点:因为它是一个数组,所以文本包含大括号和逗号等字符。因此,搜索具有特定开头的关键字并不是那么简单(ABC%
):您必须始终像%ABC%
SELECT jsondata
FROM (
SELECT
jsondata,
jsondata->'properties'->>'home' as a
FROM
temp
)s
WHERE
a LIKE '%stad%' AND a LIKE '%foot%'
你确定你有任何包含“foot”并以“stad”开头的“home”值吗?json看起来像-{“properties”:{“home”:[“football”,“stadium”,“16”]}我想在home数组上执行-%foot%和%stad%这样的操作,但是当你使用和正确时,你没有一个值同时包含这两个值。这就是我无法执行此操作的原因。我刚试过这个选择。但是,如果有更好的方法不使用价值,那也会更好。我想要实现的就是用OR和and操作在JSONB数组上执行LIKE操作。但是,这涉及到连接和分组,这是一项繁重的操作。所以,我更喜欢不涉及这个手术的东西。只需使用LIKE和and运算符。