繁体   English   中英

多语言列上的全文搜索索引

[英]Full text search index on a multilingual column

我有一个DB,其中有一个表shows了多语种列title 我想通过添加如下索引来优化全文搜索:

CREATE INDEX title_idx ON shows USING gin(to_tsvector(title));

我收到此错误:

ERROR:  functions in index expression must be marked IMMUTABLE

它基本上要求我添加语言参数以使 to_tsvector 不可变。 结果将是:

 CREATE INDEX title_idx ON shows USING gin(to_tsvector(LANGUAGE, title));

其中LANGUAGE将是我的目标语言之一。

是否可以创建适用于多种语言的索引?

是否可以创建适用于多种语言的索引?

是的,但是您需要第二列来标识文本的语言。 假设您在表中添加了一列doc_language 然后你可以写:

CREATE INDEX title_idx ON shows USING gin(to_tsvector(doc_language, title));

当然,这需要您了解主题文本的语言,这在实践中可能很难做到。 如果您不需要词干等,您可以只使用simple语言,但我猜如果这是一个选项,您已经这样做了。

作为替代方案,如果您拥有一组固定且有限的语言,则可以连接不同语言的向量 例如:

regress=> SELECT to_tsvector('english', 'cafés') || to_tsvector('french', 'cafés') || to_tsvector('simple', 'cafés');
          ?column?          
----------------------------
 'caf':2 'café':1 'cafés':3
(1 row)

这将匹配这三种语言中任何一种的cafés的 tsquery。

作为索引:

CREATE INDEX title_idx ON shows USING gin((
    to_tsvector('english', title) || 
    to_tsvector('french', title) || 
    to_tsvector('simple', title)
));

但这在查询中使用起来很笨拙,因为规划器在匹配索引 quals 方面不是很聪明。 所以我将它包装在一个函数中:

CREATE FUNCTION to_tsvector_multilang(text) RETURNS tsvector AS $$
SELECT to_tsvector('english', $1) || 
       to_tsvector('french', $1) || 
       to_tsvector('simple', $1)
$$ LANGUAGE sql IMMUTABLE;

CREATE INDEX title_idx ON shows USING gin(to_tsvector_multilang(title));

如果您愿意,您甚至可以花哨:将语言列表作为数组传递(但请记住,索引必须完全相同才能使索引匹配工作)。 将优先级与setweight一起使用, setweight ,您更喜欢英语匹配而不是法语匹配。 各种选择。

我刚刚做了一个 Postgres 函数来测试文本语言。 它并不完美,但适用于长文本。

CREATE OR REPLACE FUNCTION get_language(t text) RETURNS regconfig AS $$
DECLARE
    ret regconfig;
    BEGIN
            WITH l as ( SELECT cfgname, to_tsvector(cfgname::regconfig, title) as vector, length(to_tsvector(cfgname::regconfig, title)) as len
        FROM pg_ts_config, (select t as title) as ti)
    SELECT cfgname::regconfig
    INTO ret 
    FROM l
    WHERE len=(SELECT MIN(len) FROM l)
    ORDER BY cfgname='simple' DESC, cfgname ASC
    LIMIT 1;
    RETURN ret;
    END;
$$ LANGUAGE plpgsql;

它只是为给定的文本寻找最短的 tsvector(所以它会尝试 postgres 的每个 ts 配置)。

就我而言,我知道当前ligne的语言。 我有一个“语言”专栏。 但如果我这样做:

CREATE INDEX filmtraduction_tsindex ON filmtraduction USING GIN (
to_tsvector((case when $1=''language.fr'' then ''french'' when $1=''language.es'' then ''spanish'' else ''english'' end)::regconfig, body));

如果有“索引表达式中的函数必须标记为 IMMUTABLE”。

所以我需要创建一个不可变的函数:

 CREATE FUNCTION toregconfig(text) RETURNS regconfig AS 'select (case
 when $1=''language.fr'' then ''french'' when $1=''language.es'' then
 ''spanish'' else ''english'' end)::regconfig;' LANGUAGE SQL IMMUTABLE
 RETURNS NULL ON NULL INPUT;

然后我可以创建我的索引:

CREATE INDEX filmtraduction_tsindex ON filmtraduction USING GIN (
to_tsvector(toregconfig(language), body));

我做这样的查询:

select * from movietraduction where to_tsvector(toregconfig(language), body) @@ plainto_tsquery('foo');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM