Files
akmon/doc_news/fulltext_search_alternative.sql
2026-01-20 08:04:15 +08:00

109 lines
3.8 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 备选方案:不使用自定义函数的全文搜索索引
-- 如果IMMUTABLE函数方法失败可以使用此备选方案
-- ===================================================================
-- 方案1: 使用表达式索引 (推荐)
-- ===================================================================
-- 删除可能存在的有问题的索引
DROP INDEX IF EXISTS public.idx_contents_fts_title;
DROP INDEX IF EXISTS public.idx_contents_fts_content;
-- 删除可能有问题的函数
DROP FUNCTION IF EXISTS public.content_title_to_tsvector(TEXT);
DROP FUNCTION IF EXISTS public.content_body_to_tsvector(TEXT);
-- 方法1: 使用简单的表达式索引
CREATE INDEX IF NOT EXISTS idx_contents_fts_title_simple
ON public.ak_contents USING gin((to_tsvector('simple', title)));
CREATE INDEX IF NOT EXISTS idx_contents_fts_content_simple
ON public.ak_contents USING gin((to_tsvector('simple', content)));
-- ===================================================================
-- 方案2: 使用预计算列 (最佳性能)
-- ===================================================================
-- 添加预计算的tsvector列
DO $$
BEGIN
-- 检查列是否已存在
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'ak_contents'
AND column_name = 'title_search_vector'
) THEN
ALTER TABLE public.ak_contents
ADD COLUMN title_search_vector tsvector;
END IF;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'ak_contents'
AND column_name = 'content_search_vector'
) THEN
ALTER TABLE public.ak_contents
ADD COLUMN content_search_vector tsvector;
END IF;
END
$$;
-- 更新现有数据的搜索向量
UPDATE public.ak_contents SET
title_search_vector = to_tsvector('simple', COALESCE(title, '')),
content_search_vector = to_tsvector('simple', COALESCE(content, ''))
WHERE title_search_vector IS NULL OR content_search_vector IS NULL;
-- 创建触发器自动更新搜索向量
CREATE OR REPLACE FUNCTION public.update_content_search_vectors()
RETURNS trigger AS $$
BEGIN
NEW.title_search_vector := to_tsvector('simple', COALESCE(NEW.title, ''));
NEW.content_search_vector := to_tsvector('simple', COALESCE(NEW.content, ''));
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 创建触发器
DROP TRIGGER IF EXISTS trig_update_content_search_vectors ON public.ak_contents;
CREATE TRIGGER trig_update_content_search_vectors
BEFORE INSERT OR UPDATE ON public.ak_contents
FOR EACH ROW EXECUTE FUNCTION public.update_content_search_vectors();
-- 在预计算列上创建索引
CREATE INDEX IF NOT EXISTS idx_contents_title_search_vector
ON public.ak_contents USING gin(title_search_vector);
CREATE INDEX IF NOT EXISTS idx_contents_content_search_vector
ON public.ak_contents USING gin(content_search_vector);
-- ===================================================================
-- 查询示例
-- ===================================================================
-- 使用方案1的查询方式 (表达式索引)
/*
SELECT id, title FROM ak_contents
WHERE to_tsvector('simple', title) @@ to_tsquery('simple', 'AI');
SELECT id, title FROM ak_contents
WHERE to_tsvector('simple', content) @@ to_tsquery('simple', 'technology');
*/
-- 使用方案2的查询方式 (预计算列)
/*
SELECT id, title FROM ak_contents
WHERE title_search_vector @@ to_tsquery('simple', 'AI');
SELECT id, title FROM ak_contents
WHERE content_search_vector @@ to_tsquery('simple', 'technology');
-- 组合搜索并按相关性排序
SELECT
id, title,
ts_rank(title_search_vector, query) + ts_rank(content_search_vector, query) as rank
FROM ak_contents, to_tsquery('simple', 'AI & technology') query
WHERE title_search_vector @@ query OR content_search_vector @@ query
ORDER BY rank DESC;
*/