122 lines
3.6 KiB
Markdown
122 lines
3.6 KiB
Markdown
# IMMUTABLE函数错误最终解决方案
|
||
|
||
## 🔧 问题解决
|
||
|
||
**错误**: `ERROR: 42P17: functions in index predicate must be marked IMMUTABLE`
|
||
|
||
**最终解决方案**: 使用简单的表达式索引,完全避免自定义IMMUTABLE函数的复杂性。
|
||
|
||
## ✅ 修复内容
|
||
|
||
### 移除了复杂的IMMUTABLE函数
|
||
|
||
**之前 (复杂方案)**:
|
||
```sql
|
||
-- 创建自定义IMMUTABLE函数
|
||
CREATE FUNCTION content_title_to_tsvector(title TEXT)
|
||
RETURNS tsvector LANGUAGE sql IMMUTABLE STRICT...
|
||
|
||
-- 使用自定义函数的索引
|
||
CREATE INDEX ... USING gin(content_title_to_tsvector(title));
|
||
```
|
||
|
||
**现在 (简化方案)**:
|
||
```sql
|
||
-- 直接使用表达式索引
|
||
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. **维护简单**: 不需要管理额外的函数
|
||
|
||
## 📋 使用方法
|
||
|
||
### 全文搜索查询
|
||
|
||
```sql
|
||
-- 搜索标题
|
||
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;
|
||
```
|
||
|
||
### 高级搜索功能
|
||
|
||
```sql
|
||
-- 短语搜索
|
||
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
|