JSON 的值存在于列的 JSONB 数组中

Values of JSON exist in columns' JSONB array

我有一个棘手的查询,它试图找到将 JSON 数组列表与列 JSON 值列表进行比较的匹配项

带有 "Keywords" 列的 "Things" table 将包含如下内容:

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

查询将包含以下值:

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

我想查找列表中同时包含 "car" 和 "house" 的所有行。这是我(大部分)微弱的尝试:

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

此外,在索引方面,我假设添加 GIST 索引是我的最佳选择。

I'd like to find all the rows that have BOTH "car" and "house"

所以正确的运算符是?& - Do all of these array strings exist as top-level keys?

您的查询基本正确,更改运算符并使用 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 index:

The default GIN operator class for jsonb supports queries with top-level key-exists operators ?, ?& and ?| operators (...)