如何使用IN运算符查询jsonb数组

时间:2018-04-13 11:27:59

标签: json postgresql jsonb

我正在寻找一种方法来查询postgres jsonb字段,并在数组中使用“IN”子句。

我们假设我有一张桌子

CREATE TABLE test(
   id uuid,
   test_content jsonb,
   PRIMARY KEY(id)
);

INSERT INTO test (id, test_content) VALUES 
('aa82a8b8-33ef-4937-bd8c-8a4b40960f18', '[{"label":"a","label1":"1"},{"label":"b","label1":"2"}]'),
('ba82a8b8-33ef-4937-bd8c-8a4b40960f18', '[{"label":"c","label1":"3"}]'),
('da82a8b8-33ef-4937-bd8c-8a4b40960f18', '[{"label":"d","label1":"4"}]');

我需要选择test_content数组中的标签可能为bd的行。

我试过

SELECT * 
FROM test 
WHERE test_content @> '[{"label":"b"}]' OR test_content @> '[{"label":"d"}]'

但是当我想使用包含label12的{​​{1}}扩展我的查询时,它会变得复杂......

我需要的是3

是否可以使用jsonb运算符?

1 个答案:

答案 0 :(得分:3)

简短回答

您可以在横向连接中使用函数jsonb_array_elements(),并在value子句中的复杂表达式中使用其结果WHERE

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')

鲜明

当在一行中的数组的多个元素中满足过滤条件时,查询可能会返回重复的行,例如

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |                          test_content                          
--------------------------------------+----------------------------------------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
(2 rows)    

因此,在DISTINCT列表中使用SELECT可能是合理的:

SELECT DISTINCT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')
EXISTS子句中的

WHERE,可能会更快一些:

SELECT t.*
FROM test t
WHERE EXISTS (
    SELECT 
    FROM jsonb_array_elements(test_content)
    WHERE value->>'label' IN ('a', 'b')
    )

您还可以在需要此信息的情况下选择匹配的数组元素:

SELECT id, value
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |             value             
--------------------------------------+-------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "a", "label1": "1"}
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "b", "label1": "2"}
(2 rows)

性能比较

jsonb_array_elements()功能很昂贵。对于较大的表,由于服务器负载过重和查询执行时间过长,函数的使用可能会有问题。

虽然GIN索引可用于@>运算符的查询:

CREATE INDEX ON test USING GIN (test_content)

如果是这个功能,这是不可能的。索引支持的查询比使用该函数的查询快几十倍。