Значения JSON существуют в массиве JSONB столбцов - PullRequest
0 голосов
/ 04 июля 2018

У меня сложный запрос, который пытается найти совпадения, сравнивающие список массивов JSON со списком значений JSON в столбце

Таблица «Вещи» со столбцом «Ключевые слова» будет содержать что-то вроде:

'["car", "house", "boat"]'::JSONB

Запрос будет содержать значения:

'["car", "house"]'::JSONB

Я хотел бы найти все строки, в которых есть ОБА "машина" и "дом", содержащиеся в списке. Вот моя (в основном) слабая попытка:

SELECT
  *
FROM
  "Things"
WHERE
 "Keywords"::JSONB ?| ARRAY(
     SELECT * FROM JSONB_ARRAY_ELEMENTS('["house","car"]'::JSONB)
  )::TEXT[]

Также, когда дело доходит до индексации, я предполагаю, что добавление индекса GIST было бы моим лучшим вариантом.

1 Ответ

0 голосов
/ 04 июля 2018

Я бы хотел найти все строки, которые имеют ОБА "машина" и "дом"

Таким образом, правильный оператор - ?& - Существуют ли все эти строки массива в качестве ключей верхнего уровня?

Ваш запрос почти правильный, смените оператора и используйте jsonb_array_elements_text():

WITH "Things"("Keywords") AS (
VALUES
    ('["car", "house", "boat"]'::jsonb),
    ('["car", "boat"]'),
    ('["car", "house"]'),
    ('["house", "boat"]')
)

SELECT
  *
FROM
  "Things"
WHERE
 "Keywords" ?& array(
     SELECT jsonb_array_elements_text('["house","car"]')
  )

         Keywords         
--------------------------
 ["car", "house", "boat"]
 ["car", "house"]
(2 rows)

Запрос был бы проще, если бы аргумент мог быть записан как обычный массив текста:

SELECT
  *
FROM
  "Things"
WHERE
 "Keywords" ?& array['house', 'car']

В обоих случаях вы можете использовать индекс GIN:

Класс операторов GIN по умолчанию для jsonb поддерживает запросы с операторами существующего ключа верхнего уровня?,? & И? | операторы (...)

...