全文检索慢主因是索引未建对、查询未写对或未走索引;可通过explain("executionstats")检查executionstages.stage是否为text、totaldocsexamined与nreturned差距及indexname是否为text索引名。

全文检索慢,大概率不是 Atlas Search 或 $text 本身的问题,而是索引没建对、查询没写对,或者根本没走索引。先确认是不是真在用全文能力,再谈优化。
怎么判断你的全文查询到底走没走索引
直接跑 explain("executionStats"),重点看三个字段:
-
executionStages.stage是TEXT还是COLLSCAN?如果是后者,说明压根没用上文本索引 -
totalDocsExamined和nReturned差距极大(比如查出 5 条却扫了 50 万文档),基本等于裸跑 -
indexBounds为空,或indexName显示的是普通索引名(如title_1),那$text就是摆设
常见坑:忘了在集合上创建 text 索引,或者创建了但字段名拼错(比如查 content 却只给 body 建了索引);还有一种是用了 $regex 混在 $text 查询里,MongoDB 会直接弃用文本索引。
文本索引建得对不对,比你想象中更关键
MongoDB 一个集合只允许一个 text 索引,但它可以包含多个字段,且顺序影响权重和覆盖能力:
- 字段必须显式声明为
"text"类型:db.articles.createIndex({ title: "text", content: "text" }) - 如果想让某字段权重更高(比如标题比正文更重要),得加
weights:{ weights: { title: 10, content: 1 } } - 别把
text索引和普通查询字段混在一个复合索引里(例如{ status: 1, content: "text" }),MongoDB 不支持这种组合 - 索引创建后,要等后台构建完成(
db.currentOp()可查),期间查询可能降级为全表扫描
另外注意:文本索引不支持前缀匹配("poet*"),只支持词干匹配("poet" 能命中 "poetry"),如果业务需要通配,$regex 是唯一选择,但必须接受性能代价。
Atlas Search 是更快,但不是无脑替换
Atlas Search 是独立于传统 $text 的新引擎,底层用 Lucene,支持分词、同义词、模糊搜索、高亮等,但切换前得看清约束:
- 它只存在于 MongoDB Atlas 托管服务中,自建集群无法使用
- 需要单独定义 search index(JSON Schema),不能复用已有
text索引,数据同步有轻微延迟(秒级) - 查询语法完全不同:
$search替代$text,且必须走aggregate(),不能用于find() - 免费层有每日查询额度限制,高频场景需评估成本
如果你的场景是“用户搜商品关键词+自动纠错+按相关性排序”,Atlas Search 值得切;如果只是后台管理端查日志里的“error”“timeout”这类固定词,$text + 合理索引足矣,换 Atlas 反而增加运维复杂度。
真正卡住性能的,往往不是引擎选型,而是没意识到 text 索引不支持范围过滤(比如 { publishedAt: { $gt: ISODate(...) } })与全文查询共存时,MongoDB 会先全文扫再过滤——这时候得靠覆盖索引或预聚合来缓解。这点容易被忽略,但实际影响极大。











