Postgres 中的复合 JSONB 数组查询?
Composite JSONB array query in Postgres?
Table: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"]]');
对于 returns 所有行的查询,正确的 Postgres 语法是什么
content
元素中至少有一个满足 (first element = "first 1")
AND (second element ILIKE "%3%")
?
也就是说,在上面的示例中,它应该 select 第 1 行和第 3 行,而不是第 2 行或第 4 行。
奖金问题:执行此类查询的最有效方法是什么(如果有多种选择)?使用 pg_trgm
通过 JSONB 查看 GIN 是否有意义? (有数百万行,内部字符串值通常为 10-100 个字符长,每个 content
列表包含 0-1000 个列表(通常为 0)。)
谢谢!
您应该拆分顶级数组并从那里检查元素:
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 在评论中的查询更好,因为它应该更高效,尤其是当内容可以包含 1000 多个元素时:
select * from test
where exists
(select 1
from jsonb_array_elements(content) jae(elems)
where elems ->> 0 = 'first 1'
and elems ->> 1 ilike '%3%'
);
内部 select 将数组元素扩展到单独的行中 jsonb_array_elements,外部 select 进行您想要的过滤。请参阅 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%'
Table: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"]]');
对于 returns 所有行的查询,正确的 Postgres 语法是什么
content
元素中至少有一个满足 (first element = "first 1")
AND (second element ILIKE "%3%")
?
也就是说,在上面的示例中,它应该 select 第 1 行和第 3 行,而不是第 2 行或第 4 行。
奖金问题:执行此类查询的最有效方法是什么(如果有多种选择)?使用 pg_trgm
通过 JSONB 查看 GIN 是否有意义? (有数百万行,内部字符串值通常为 10-100 个字符长,每个 content
列表包含 0-1000 个列表(通常为 0)。)
谢谢!
您应该拆分顶级数组并从那里检查元素:
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 在评论中的查询更好,因为它应该更高效,尤其是当内容可以包含 1000 多个元素时:
select * from test
where exists
(select 1
from jsonb_array_elements(content) jae(elems)
where elems ->> 0 = 'first 1'
and elems ->> 1 ilike '%3%'
);
内部 select 将数组元素扩展到单独的行中 jsonb_array_elements,外部 select 进行您想要的过滤。请参阅 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%'