[英]How to implement Full-Text search in multilingual content in SQL Server
[英]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.