【发布时间】:2019-11-26 11:24:41
【问题描述】:
在查找表中的第一行时,Pgsql 无法对包含数组的 jsonb 列执行索引全文搜索。
表格只不过是Id 和Foo 即jsonb 列。
情况是我有一个空数据库,在 make_tsvector 函数上预定义了 gin 索引 repro_fts_idx。 make_tsvector 从给定的 jsonb 列创建 tsvector。
当我在表格中添加一个新项目时,我希望它以tsvector 的形式出现在make_tsvector 函数中。在那里。
另外,我希望如果我对其运行全文搜索查询,它会出现在搜索结果中。但是,情况并非如此,因为它专门为第一行返回空。它根本没有考虑到它。
如果我再添加一个完全相同的行,系统就可以使用相同的查询找到它。
这里有一个小的复制案例:
-- drop table cp."Repro" cascade
CREATE TABLE cp."Repro" (
"Id" serial NOT NULL,
"Foo" jsonb NULL
);
CREATE OR REPLACE FUNCTION cp.make_tsvector(in_t cp."Repro")
RETURNS tsvector
LANGUAGE plpgsql
IMMUTABLE
AS $function$ begin
return to_tsvector(jsonb_agg(x.prop))
from (SELECT CONCAT( jsonb_array_elements(in_t."Foo") ->> 'Name', ' ', jsonb_array_elements(in_t."Foo") ->> 'Address' ) as prop from cp."Repro" f) as x;
END;
$function$
;
CREATE INDEX repro_fts_idx ON cp."Repro" USING gin (cp.make_tsvector(cp."Repro".*)) WITH (fastupdate=off, gin_pending_list_limit='64');
INSERT INTO cp."Repro"
("Foo")
VALUES('[{"Name": "Sup", "Address": "Adress", "IsCurrent": true}]');
-- just in case it's the indexing issue
-- REINDEX INDEX cp.repro_fts_idx;
select * from cp."Repro"
select cp.make_tsvector(x) from cp."Repro" x
select * from ts_stat('select cp.make_tsvector(x) from cp."Repro" x')
-- explain analyze
SELECT *
FROM "cp"."Repro" x where cp.make_tsvector(x) @@ 'sup:*'::tsquery
INSERT INTO cp."Repro"
("Foo")
VALUES('[{"Name": "Sup", "Address": "Adress", "IsCurrent": true}]');
-- explain analyze
SELECT *
FROM "cp"."Repro" x where cp.make_tsvector(x) @@ 'sup:*'::tsquery
UPD:答案
函数错误,因为它同时引用了输入行和整个表。 正确的函数是:
CREATE OR REPLACE FUNCTION cp.make_tsvector(in_t cp."Repro")
RETURNS tsvector
LANGUAGE plpgsql
IMMUTABLE
AS $function$
BEGIN
return string_agg(lower(regexp_replace(coalesce(x::text, ''), '[|&\\*:()'']+', ' ', 'g')), ' ')::tsvector FROM (SELECT CONCAT( jsonb_array_elements(in_t."Foo") ->> 'Name', ' ', jsonb_array_elements(in_t."Foo") ->> 'Address' ) AS x) AS x;
END;
$function$
;
【问题讨论】:
标签: postgresql full-text-search jsonb