SearchVector + PostgreSQL 不够用,因其不支持中文分词、模糊/同义/拼写容错,且无法动态加权排序或聚合统计;需改用 Elasticsearch 配合异步同步、严格 DSL 控制与异常降级机制。

为什么 SearchVector + PostgreSQL 不够用?
当数据量超过 10 万行、查询词带模糊/同义/拼写容错需求,或需要按相关性动态排序时,Django 自带的 SearchVector 就开始掉链子:查不到“笔记本电脑”却能查到“笔 记 本 电 脑”,不支持中文分词,也没办法对标题加权高于正文。这时候不是调参能解决的——是底层引擎能力边界问题。
- PostgreSQL 全文检索依赖字典和 tsvector 预计算,中文需额外配置
zhparser插件,部署麻烦且更新索引要锁表 -
SearchRank的权重模型固定,没法按业务定义“标题匹配比正文匹配重要 3 倍” - 无法做聚合统计(比如“近一周搜索量 Top10 关键词”),因为没 query log 和实时分析管道
怎么把 Django 模型同步到 Elasticsearch?别用 django-elasticsearch-dsl
这个包看似省事,但默认开启实时 signal 同步,在高并发写入场景下容易丢数据、卡主线程,且 schema 变更后重建索引必须手动跑命令,线上不敢轻易操作。
- 改用异步任务驱动:在 model
save()里只发一个update_es_document.delay(instance.id),由 Celery 拉取最新数据构造文档 - ES mapping 显式声明字段类型,尤其是中文字段必须设
"analyzer": "ik_max_word"(用 ik 分词器),别依赖 dynamic mapping - 索引名带版本号,例如
product_v2,上线新 schema 前先建product_v3,同步完再原子切换 alias
elasticsearch-py 查询怎么避免 OOM 和超时?
直接用 search() 发裸请求,很容易在结果集大或网络抖动时卡死进程,尤其当用户输了个空字符串或通配符 * 时,ES 默认返回 10 条,但 size 被设成 10000 就会触发 circuit breaker。
强戈环形山: q15040409-刻画家功能概述强戈环形山: q15040409-刻画家是一项面向实际任务的技能,主要用于平顶山: 维西翁: 1:1.0. 塔格斯: rap.github: 自动化。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。核心要点使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。从功能定位来看,该
- 永远设置
"timeout": "5s"和"terminate_after": 1000(单 shard 最多查 1000 条就停) - 分页不用 from/size,改用
search_after+ 排序字段值,避免深度翻页性能断崖 - 查询 DSL 里禁用
match_all和未加bool.must保护的wildcard,前端传参前先用正则过滤掉*、?等危险字符
Django 视图里怎么安全接住 ES 返回的异常?
ConnectionError、NotFoundError、RequestError 这三类抛出来不是让你 try-except 吞掉的,而是要区分响应——前者该降级回 DB 模糊查,后者说明索引根本不存在,得告警而不是 500。
- 封装一个
es_search()工具函数,在 catchConnectionError后自动 fallback 到Model.objects.filter(name__icontains=...) -
NotFoundError出现时立刻记录日志并触发 Sentry 告警,这通常意味着索引未创建或 alias 指向错误 - 所有 ES 查询结果必须经过
if response.get("hits", {}).get("hits"):判空,ES 返回空数组不算错,但response["hits"]["total"]在 7.x 后是 dict,别直接int()
最常被跳过的其实是分词器验证:上线前拿真实中文词(如“蓝牙耳机”“Type-C”)跑一遍 _analyze API,看是否拆成预期 token。没验过就上生产,搜不到东西时再查就晚了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










