查询未传collation时索引被忽略,因mongodb仅匹配完全一致的collation(含所有键值),否则直接跳过该索引;分片集合强制要求collation为{"locale":"simple"},中文等locale仅支持非分片场景。

查询没传 collation,索引直接被忽略
MongoDB 默认用 "simple" 排序规则匹配索引,哪怕你建索引时指定了 collation={"locale": "zh"},只要查询不带完全一致的 collation 参数,就压根不会走这个索引——不是“没选上”,是根本不在候选列表里。
常见错误现象:db.collection.find({"name": "张三"}) 查不到结果,但加了 collation 就能命中;执行 explain() 显示 "indexBounds": [] 或 "stage": "COLLSCAN"。
- 必须在查询中显式传入和建索引时一模一样的
collation对象,包括所有键名和值(比如{"locale": "zh", "strength": 1}不等于{"locale": "zh"}) - 使用聚合时,
$match阶段也得带collation,不能只在顶层加 - Ruby 驱动写法示例:
collection.find({"name": "张三"}, "collation" => {"locale" => "zh"})
locale 值无效或版本不支持
locale 不是随便填的字符串,必须是 ICU 支持的有效 ID,且 MongoDB 版本要够新。填错会静默失败——索引建成了,但实际无效。
常见错误现象:建索引成功、getIndexes() 看起来正常,但查询始终全表扫;插入含中文文档后,$text 搜索“教程”返回空。
- 可用值参考:
"en"、"zh"、"fr_CA";避免用"en_US"或"zh_CN",部分 4.2–5.0 版本会解析失败 -
collation对text索引有额外限制:不能和weights、default_language等选项共存,否则报错Cannot specify collation on a text index - 确认 MongoDB 版本 ≥ 4.2(
zhlocale 支持从 4.2 开始),用db.version()检查
strength 设置不符合查询语义
strength 决定比较粒度,设错会导致“看似该命中却没命中”。比如想实现大小写不敏感,却用了 strength: 2,结果 "Alice" 和 "alice" 仍被当作不同值。
常见错误现象:建了带 collation 的唯一索引,但 "Test" 和 "test" 还能同时插入;或者排序结果不符合预期(如重音字符排错位)。
-
strength: 1:只比较基础字符,真正忽略大小写、重音、变体(适合绝大多数中文/英文模糊匹配场景) -
strength: 2:区分重音但忽略大小写(如cote≠coté) -
strength: 3:区分大小写和重音(默认二进制行为) - 建索引和查询必须用相同
strength,否则不匹配
分片集合里 collation 被强制覆盖为 simple
对已分片的集合执行 shardCollection 时,MongoDB 要求索引必须用 collation: {locale: "simple"},否则命令失败。这意味着你没法在分片集合上建带 zh 的 collation 索引。
常见错误现象:shardCollection 报错 collation must be {locale: "simple"};或建索引成功但查询不生效,explain() 显示没走索引。
- 分片键索引、唯一索引、哈希索引都受此限制,无法绕过
- 如果业务强依赖中文 collation,只能放弃分片,或改用应用层预处理(如 Jieba 分词 + keyword 索引)
- 非分片集合不受限,但要注意单节点容量瓶颈











