JSONB массив содержит операторы OR и AND - PullRequest
0 голосов
/ 19 сентября 2018

Рассмотрим таблицу temp (jsondata jsonb)

Postgres предоставляет способ запроса объекта массива jsonb для проверки содержимого, используя

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%'

ИЛИ операцию с LIKE можно выполнить с помощью -

SELECT DISTINCT jsondata 
FROM temp,jsonb_array_elements_text(temp.jsondata->'properties'->'home') 
WHERE value like '%foot%' OR value like 'stad%'

Но я не могу выполнить операцию И сОператор LIKE в массиве JSONB содержит.

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

После удаления массива с помощью jsonb_array_elements() вы можете проверить values, удовлетворяющее одному из условий, и суммировать их в группы по исходным строкам, например:

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) 
0 голосов
/ 19 сентября 2018

demo: db <> fiddle

Я бы преобразовал массив в текст.Затем вы можете искать ключевые слова с каждым строковым оператором.

Недостаток: поскольку это был массив, текст содержит такие символы, как фигурные скобки и запятые.Поэтому поиск по ключевому слову с определенным началом не так прост (ABC%): всегда нужно искать как %ABC%

SELECT jsondata
FROM (
    SELECT 
        jsondata, 
        jsondata->'properties'->>'home' as a
    FROM 
        temp
)s
WHERE 
    a LIKE '%stad%' AND a LIKE '%foot%'
0 голосов
/ 19 сентября 2018

У меня есть следующее, но это было немного странно.Возможно, есть лучший способ, но это работает, я думаю.

Идея состоит в том, чтобы найти подходящие записи массива JSON, а затем собрать результаты.В условии соединения мы проверяем, что в массиве «match» ожидаемое количество записей.

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