【问题标题】:Postgres Full Text Search Jsonb Array column does not show first rowPostgres全文搜索Jsonb数组列不显示第一行
【发布时间】:2019-11-26 11:24:41
【问题描述】:

在查找表中的第一行时,Pgsql 无法对包含数组的 jsonb 列执行索引全文搜索。

表格只不过是IdFoojsonb 列。

情况是我有一个空数据库,在 make_tsvector 函数上预定义了 gin 索引 repro_fts_idxmake_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


    【解决方案1】:

    你的功能肯定是错的。它不应同时引用其输入记录in_t 和整个基础表cp."Repro"。 (因为它指的是cp."Repro",所以它并不是真正的不可变的。当你在你的函数的不变性上对系统撒谎时,就会发生坏事。)

    由于在插入第一行时表是空的,因此从函数内部的空表中进行选择不会给出任何结果,从而产生要索引的 NULL 结果。这可以通过以下方式看到:

    truncate cp."Repro" ;
    select cp.make_tsvector(row(1,'[{"Name": "Sup", "Address": "Adress", "IsCurrent": true}]'));
     make_tsvector 
    ---------------
     (null)
    

    即使您的 make_tsvector 没有损坏,它似乎仍然没用。它基本上只是对 to_tsvector 的重新实现。它应该完成什么?

    【讨论】:

    • 基本上你是对的,你指向的地方的功能是错误的。用回复更新了问题。
    猜你喜欢
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    相关资源
    最近更新 更多