122 lines
4.2 KiB
Python
122 lines
4.2 KiB
Python
|
|
"""清理废案 search_title_suggestions 相关对象。
|
||
|
|
|
||
|
|
设计:产品迭代决定只展示 keyword 续接词,titles 段(真实文章 id 提示)被砍。
|
||
|
|
但 0009 迁移里建的相关对象还在:
|
||
|
|
- search_title_suggestions 表 + 3 个 GIN/B-tree 索引
|
||
|
|
- articles trigger trg_articles_rebuild_title_suggestions
|
||
|
|
- rebuild_title_suggestions() PL/pgSQL 函数
|
||
|
|
|
||
|
|
每篇文章 INSERT/UPDATE 都要跑 trigger(性能损耗),删干净。
|
||
|
|
|
||
|
|
也清理:
|
||
|
|
- app/models/search_title_suggestion.py 文件(本次 commit 不删文件,只删 __init__ 引用)
|
||
|
|
- app/scripts/backfill_search_suggestions.py 现在回灌的也是 search_title_suggestions
|
||
|
|
→ 整体替换成"无 op 脚本"(或者改名为只跑一次 refresh_search_keywords)
|
||
|
|
|
||
|
|
Revision ID: 0011
|
||
|
|
Revises: 0010
|
||
|
|
Create Date: 2026-06-15
|
||
|
|
"""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Sequence, Union
|
||
|
|
|
||
|
|
import sqlalchemy as sa
|
||
|
|
from alembic import op
|
||
|
|
|
||
|
|
|
||
|
|
revision: str = "0011"
|
||
|
|
down_revision: Union[str, None] = "0010"
|
||
|
|
branch_labels = None
|
||
|
|
depends_on = None
|
||
|
|
|
||
|
|
|
||
|
|
def upgrade() -> None:
|
||
|
|
# 1) 删 trigger(挂 articles 上)
|
||
|
|
op.execute("DROP TRIGGER IF EXISTS trg_articles_rebuild_title_suggestions ON articles")
|
||
|
|
|
||
|
|
# 2) 删 trigger 函数
|
||
|
|
op.execute("DROP FUNCTION IF EXISTS rebuild_title_suggestions()")
|
||
|
|
|
||
|
|
# 3) 删表 + 索引(ON DELETE CASCADE 让 articles delete 一起清)
|
||
|
|
op.drop_index("ix_search_title_suggestions_published", table_name="search_title_suggestions")
|
||
|
|
op.drop_index("ix_search_title_suggestions_article", table_name="search_title_suggestions")
|
||
|
|
op.drop_index("ix_search_title_suggestions_prefix", table_name="search_title_suggestions")
|
||
|
|
op.drop_table("search_title_suggestions")
|
||
|
|
|
||
|
|
|
||
|
|
def downgrade() -> None:
|
||
|
|
# 重新建表(产品迭代回滚时用 — schema 跟 0009 一致)
|
||
|
|
op.create_table(
|
||
|
|
"search_title_suggestions",
|
||
|
|
sa.Column("id", sa.BigInteger, primary_key=True),
|
||
|
|
sa.Column(
|
||
|
|
"article_id",
|
||
|
|
sa.BigInteger,
|
||
|
|
sa.ForeignKey("articles.id", ondelete="CASCADE"),
|
||
|
|
nullable=False,
|
||
|
|
),
|
||
|
|
sa.Column("title_lang", sa.String(8), nullable=False, server_default="zh"),
|
||
|
|
sa.Column("prefix_keys", sa.ARRAY(sa.Text), nullable=False),
|
||
|
|
sa.Column("published_at", sa.DateTime(timezone=True), nullable=True),
|
||
|
|
sa.Column(
|
||
|
|
"created_at",
|
||
|
|
sa.DateTime(timezone=True),
|
||
|
|
nullable=False,
|
||
|
|
server_default=sa.text("now()"),
|
||
|
|
),
|
||
|
|
)
|
||
|
|
op.create_index(
|
||
|
|
"ix_search_title_suggestions_prefix",
|
||
|
|
"search_title_suggestions",
|
||
|
|
["prefix_keys"],
|
||
|
|
postgresql_using="gin",
|
||
|
|
)
|
||
|
|
op.create_index(
|
||
|
|
"ix_search_title_suggestions_article",
|
||
|
|
"search_title_suggestions",
|
||
|
|
["article_id"],
|
||
|
|
)
|
||
|
|
op.create_index(
|
||
|
|
"ix_search_title_suggestions_published",
|
||
|
|
"search_title_suggestions",
|
||
|
|
["published_at"],
|
||
|
|
)
|
||
|
|
op.execute(
|
||
|
|
"""
|
||
|
|
CREATE OR REPLACE FUNCTION rebuild_title_suggestions() RETURNS TRIGGER AS $$
|
||
|
|
DECLARE
|
||
|
|
src_text text;
|
||
|
|
src_lang text;
|
||
|
|
max_len int := 50;
|
||
|
|
BEGIN
|
||
|
|
DELETE FROM search_title_suggestions WHERE article_id = NEW.id;
|
||
|
|
IF NEW.title_zh IS NOT NULL AND length(NEW.title_zh) > 0 THEN
|
||
|
|
src_text := NEW.title_zh;
|
||
|
|
src_lang := 'zh';
|
||
|
|
ELSIF NEW.title IS NOT NULL AND length(NEW.title) > 0 THEN
|
||
|
|
src_text := NEW.title;
|
||
|
|
src_lang := 'src';
|
||
|
|
ELSE
|
||
|
|
RETURN NEW;
|
||
|
|
END IF;
|
||
|
|
src_text := substring(src_text, 1, max_len);
|
||
|
|
INSERT INTO search_title_suggestions
|
||
|
|
(article_id, title_lang, prefix_keys, published_at)
|
||
|
|
SELECT NEW.id, src_lang,
|
||
|
|
ARRAY(SELECT substring(src_text, 1, n)
|
||
|
|
FROM generate_series(1, length(src_text)) AS n),
|
||
|
|
NEW.published_at;
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
"""
|
||
|
|
)
|
||
|
|
op.execute(
|
||
|
|
"""
|
||
|
|
CREATE TRIGGER trg_articles_rebuild_title_suggestions
|
||
|
|
AFTER INSERT OR UPDATE OF title_zh, title, published_at ON articles
|
||
|
|
FOR EACH ROW EXECUTE FUNCTION rebuild_title_suggestions();
|
||
|
|
"""
|
||
|
|
)
|