Postgres中的复合JSONB数组查询?

时间:2019-06-06 19:01:37

标签: postgresql jsonb

表: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)。)

谢谢!

2 个答案:

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