在我最初的回答中,我建议对文本进行简单的转换:tags::text。然而,虽然大多数从基本类型到文本的转换都定义为IMMUTABLE,但数组类型并非如此。显然是因为(quoting Tom Lane in a post to pgsql-general):
因为它是通过 array_out/array_in 实现的,而不是更多
直接方法,并且那些被标记为稳定的,因为它们可能
调用非不可变元素 I/O 函数。
我的大胆强调。
我们可以解决这个问题。一般情况不能标记为IMMUTABLE。但是对于手头的情况(将citext[] 或text[] 转换为text),我们可以安全地假设不变性。创建一个简单的IMMUTABLE SQL 函数来包装函数。但是,我的简单解决方案的吸引力现在几乎消失了。您不妨将 array_to_string() 包装起来(就像您已经考虑过的那样),类似的考虑也适用。
对于citext[](如果需要,为text[] 创建单独的函数):
要么(基于对text 的普通转换):
CREATE OR REPLACE FUNCTION f_ciarr2text(citext[])
RETURNS text LANGUAGE sql IMMUTABLE AS 'SELECT $1::text';
这样更快。
或者(使用array_to_string() 获得不带花括号的结果):
CREATE OR REPLACE FUNCTION f_ciarr2text(citext[])
RETURNS text LANGUAGE sql IMMUTABLE AS $$SELECT array_to_string($1, ',')$$;
这更正确一点。
那么:
CREATE INDEX doc_search_idx ON documents USING gin (
to_tsvector('english', COALESCE(f_ciarr2text(tags), '')
|| ' ' || COALESCE(notes,'')));
我确实没有使用像in your answer这样的多态类型ANYARRAY,因为我知道text[]或citext[]是安全的,但我不能保证所有 其他数组类型。
在 Postgres 9.4 中测试并为我工作。
我在两个字符串之间添加了一个空格,以避免串联字符串之间的误报匹配。有一个example in the manual。
如果您有时只想搜索 tags 或 notes,请考虑使用多列索引:
CREATE INDEX doc_search_idx ON documents USING gin (
to_tsvector('english', COALESCE(f_ciarr2text(tags), '')
, to_tsvector('english', COALESCE(notes,''));
您所指的风险主要适用于时间函数,这些函数用于referenced question。如果涉及时区(或仅涉及timestamptz 类型),则结果实际上不是不可变的。我们不会在这里对不变性撒谎。我们的函数实际上是IMMUTABLE。 Postgres 无法从它使用的一般实现中分辨出来。
相关
通常人们认为他们需要text search,而使用三元索引的相似性搜索会更合适:
在这种确切情况下不相关,但在使用 citext 时,请考虑: