Files
akmon/doc_news/IMMUTABLE_ERROR_FINAL_SOLUTION.md
2026-01-20 08:04:15 +08:00

3.6 KiB
Raw Blame History

IMMUTABLE函数错误最终解决方案

🔧 问题解决

错误: ERROR: 42P17: functions in index predicate must be marked IMMUTABLE

最终解决方案: 使用简单的表达式索引完全避免自定义IMMUTABLE函数的复杂性。

修复内容

移除了复杂的IMMUTABLE函数

之前 (复杂方案):

-- 创建自定义IMMUTABLE函数
CREATE FUNCTION content_title_to_tsvector(title TEXT) 
RETURNS tsvector LANGUAGE sql IMMUTABLE STRICT...

-- 使用自定义函数的索引
CREATE INDEX ... USING gin(content_title_to_tsvector(title));

现在 (简化方案):

-- 直接使用表达式索引
CREATE INDEX IF NOT EXISTS idx_contents_title_gin 
ON public.ak_contents USING gin((to_tsvector('simple'::regconfig, title)));

CREATE INDEX IF NOT EXISTS idx_contents_content_gin 
ON public.ak_contents USING gin((to_tsvector('simple'::regconfig, content)));

🎯 优势

  1. 简单可靠: 避免自定义函数的复杂性
  2. 兼容性强: 适用于所有PostgreSQL版本
  3. 性能良好: 表达式索引同样高效
  4. 维护简单: 不需要管理额外的函数

📋 使用方法

全文搜索查询

-- 搜索标题
SELECT id, title, published_at 
FROM ak_contents 
WHERE to_tsvector('simple', title) @@ to_tsquery('simple', 'AI');

-- 搜索内容
SELECT id, title, LEFT(content, 200) as preview
FROM ak_contents 
WHERE to_tsvector('simple', content) @@ to_tsquery('simple', 'technology');

-- 组合搜索
SELECT id, title, published_at
FROM ak_contents 
WHERE to_tsvector('simple', title) @@ to_tsquery('simple', 'AI | machine')
   OR to_tsvector('simple', content) @@ to_tsquery('simple', 'AI | machine')
ORDER BY published_at DESC;

-- 相关性排序
SELECT id, title,
       ts_rank(to_tsvector('simple', title), query) + 
       ts_rank(to_tsvector('simple', content), query) as rank
FROM ak_contents, to_tsquery('simple', 'artificial & intelligence') query
WHERE to_tsvector('simple', title) @@ query
   OR to_tsvector('simple', content) @@ query
ORDER BY rank DESC;

高级搜索功能

-- 短语搜索
SELECT * FROM ak_contents 
WHERE to_tsvector('simple', title) @@ phraseto_tsquery('simple', 'artificial intelligence');

-- 自然语言搜索
SELECT * FROM ak_contents 
WHERE to_tsvector('simple', content) @@ plainto_tsquery('simple', 'machine learning algorithms');

-- 搜索高亮
SELECT id, title,
       ts_headline('simple', content, to_tsquery('simple', 'AI'), 
                  'MaxWords=35, MinWords=15, ShortWord=3, HighlightAll=FALSE') as highlight
FROM ak_contents 
WHERE to_tsvector('simple', content) @@ to_tsquery('simple', 'AI');

🚀 部署状态

状态: 问题完全解决

  • 移除了有问题的IMMUTABLE函数
  • 使用简单可靠的表达式索引
  • 保持高性能全文搜索功能
  • 支持所有PostgreSQL/Supabase版本

📝 升级说明

如果您之前部署过有IMMUTABLE函数的版本

  1. 自动清理: 新版本会自动删除旧的索引
  2. 重新创建: 自动创建新的简化索引
  3. 查询兼容: 查询方式略有变化,请参考上面的示例

🎉 结论

通过使用简单的表达式索引而不是自定义IMMUTABLE函数我们彻底解决了 ERROR: 42P17 错误,同时保持了优秀的全文搜索性能。

这个解决方案更加:

  • 🔧 简单: 无需维护自定义函数
  • 🛡️ 可靠: 避免版本兼容性问题
  • 高效: 查询性能依然优秀
  • 🌐 通用: 适用于所有环境

修复时间: 2025年6月18日
问题状态: 已完全解决
兼容性: 全版本PostgreSQL/Supabase