我有一个数据库,其中有一个表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
将成为我的目标语言之一。
是否可以创建适用于多种语言的索引?
答案 0 :(得分:33)
是否可以创建适用于多种语言的索引?
是的,但您需要第二列来标识文本的语言。假设您在表中添加了一列doc_language
;然后你可以写:
CREATE INDEX title_idx ON shows USING gin(to_tsvector(doc_language, title));
当然,这要求您了解主题文本的语言,这在实践中很难实现。如果你不需要词干等,你可以使用simple
语言,但我猜你已经完成了它,如果它是一个选项。
作为替代方案,如果您拥有固定且有限的一组语言,则可以连接不同语言的向量。 E.g:
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)
));
但是在查询中使用这一点很笨拙,因为规划者在匹配索引码时并不是很聪明。所以我将它包装在一个函数中:
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
的优先级,因此您更喜欢英语匹配,法语匹配。各种选择。
答案 1 :(得分:4)
我刚刚制作了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配置)。
答案 2 :(得分:0)
就我而言,我知道当前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');