fix(analytics): 词库单字MySQL预览拒扫+IntegrityError 409+MATCH短语净化

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-04 19:48:30 +08:00
parent 0c14be0777
commit c7b3ce9d1c
3 changed files with 55 additions and 5 deletions
+10 -3
View File
@@ -69,16 +69,23 @@ async def preview_count(
口径注:MySQL MATCH 路径不扣排除词(预览=上限,排除词在扫描时精确
生效);LIKE 路径(测试库)精确扣。前端文案「预计命中」体现上限语义。
单字词在 MySQL 拒预览(ValueError)——ngram 对单字无用,落 LIKE 前导
通配全扫(86 万行实测 ~16s,b41e8fa0 迁移记录),添加后从命中列表观察。
"""
word = (word or "").strip()
if not word:
return 0
conds = [Message.text.is_not(None), Message.text != ""]
dialect = session.bind.dialect.name if session.bind else ""
if dialect == "mysql" and len(word) >= 2:
if len(word) < 2 and dialect == "mysql":
raise ValueError("单字词不做预览(MySQL 全扫);添加后从命中列表观察")
conds = [Message.text.is_not(None), Message.text != ""]
if dialect == "mysql":
# 短语净化:剥 " 与 * —— BOOLEAN MODE 里裸引号/星号是语法符,
# 混入会 1064 语法错;剥后包引号做整词短语匹配。
phrase = word.replace('"', "").replace("*", "")
conds.append(
sa.text("MATCH(message.text) AGAINST (:w IN BOOLEAN MODE)")
.bindparams(w=f'"{word}"')
.bindparams(w=f'"{phrase}"')
)
stmt = sa.select(sa.func.count()).select_from(Message).where(*conds)
n = (await session.execute(stmt)).scalar_one()