表:test
,JSONB列:content
:
create table test (id bigserial primary key, content jsonb);
content
包含一个定长列表列表:
insert into test values (1, '[["first 1", "second 3"]]');
insert into test values (2, '[["first 1", "second 2"], ["first 2", "second 3"]]');
insert into test values (3, '[["first 1", "second 2"], ["first 1", "second 3"]]');
insert into test values (4, '[["first 2", "second 3"], ["first 1", "second 2"], ["first 1", "second 2"]]');
返回所有行的查询的正确Postgres语法是什么
至少content
个元素之一满足(first element = "first 1")
和(second element ILIKE "%3%")
?
也就是说,在上面的示例中,它应该选择第1行和第3行,而不是第2行或第4行。
奖金问题:进行此类查询的最有效方法是什么(如果有多种选择)?使用pg_trgm
通过JSONB查看GIN是否有意义? (有数百万行,内部字符串值通常为10-100个字符,每个content
列表包含0-1000s列表(最通常为0)。)
谢谢!
答案 0 :(得分:3)
您应该将顶级数组分开,然后从那里检查元素:
select distinct id, content
FROM test
JOIN lateral (
select elems
FROM jsonb_array_elements(content) jae(elems)
) all_arrays ON TRUE
WHERE elems ->> 0 = 'first 1'
and elems ->> 1 ilike '%3%'
ORDER BY 1;
关于执行此操作的最佳方法,这在很大程度上取决于您的实际数据-多少行,这些jsonb结构的大小等。不过,总的来说,像ilike'%3%'这样的搜索会有所帮助来自基于pg_trgm的索引,因为它们不能使用传统的btree索引。
编辑:在注释中使用@Abelisto的查询效果更好,因为它应具有更高的性能,尤其是在内容可以包含数千个元素的情况下:
select * from test
where exists
(select 1
from jsonb_array_elements(content) jae(elems)
where elems ->> 0 = 'first 1'
and elems ->> 1 ilike '%3%'
);
答案 1 :(得分:1)
内部选择使用jsonb_array_elements将数组元素扩展为单独的行,外部选择执行所需的过滤。有关实时示例,请参见SQL Fiddle。
select * from (
select id, jsonb_array_elements(content) as item from test
) as expandedtest
where item->>0 like 'first 1' and item->>1 like '%3%'