MongoDB中无原生“大小写不敏感索引”,但可通过createIndex()配合collation实现:指定locale:"en"与strength:2,使字符串比较忽略大小写;查询时必须显式传递相同collation才能命中索引,否则索引失效。

用 collation 创建大小写不敏感索引
MongoDB 本身没有“大小写不敏感索引”这种独立类型,但可以通过在 createIndex() 中指定 collation 实现等效效果。关键不是改索引结构,而是定义字段比较时的语言规则。
默认情况下,MongoDB 字符串比较是二进制的(区分大小写、变音符号),collation 能覆盖这个行为。它必须和索引字段一起声明,且查询时也要显式带上相同 collation 才能命中索引——这点极易被忽略。
-
locale: "en"是最常用选项,启用英语规则(自动忽略大小写、处理常见词干) -
caseLevel: false(默认)已隐含大小写不敏感;设为true反而会额外加一个排序层级,一般不用 -
strength: 2表示只比较基础字符(即忽略大小写和变音符号),strength: 1连空格和标点都忽略,慎用 - 索引一旦带
collation,就不能被不带该collation的查询使用——哪怕字段完全匹配
示例:为 username 字段建大小写不敏感索引
db.users.createIndex({ username: 1 }, { collation: { locale: "en", strength: 2 } })
之后查询必须写成:
db.users.find({ username: "Alice" }).collation({ locale: "en", strength: 2 })
为什么 $text 索引不能替代 collation
$text 索引确实支持模糊、分词、停用词过滤,但它和大小写不敏感是两回事:它默认就忽略大小写,但代价是只能用于 $text 查询,且无法做精确匹配或范围查询。
-
$text索引要求字段必须是字符串,且整个字段参与全文分析,不能只针对部分值做等值查找 -
$text查询返回结果无顺序保证,除非手动加$meta: "textScore"排序,性能开销更大 - 如果业务需要
{ username: "alice" }这样的精确匹配,或{ username: { $gt: "a" } }这样的范围查询,$text完全不适用 -
$text和collation不能共存于同一查询——MongoDB 明确禁止混合使用
复合索引中 collation 的作用范围
collation 是索引级配置,不是字段级。一旦指定,它影响整个索引的所有字符串字段,但对非字符串字段(如数字、日期)无影响。
- 例如:
db.logs.createIndex({ user: 1, level: -1 }, { collation: { locale: "en" } }),其中user字符串字段按英语规则比较,level数字字段仍按数值大小排序 - 如果复合索引里有多个字符串字段,它们共享同一个
collation规则——不能给first_name用en,last_name用fr - 查询时所有涉及字符串比较的条件,都必须与索引的
collation完全一致,否则索引失效
容易被忽略的兼容性和性能陷阱
带 collation 的索引在旧版本 MongoDB(
- 索引体积通常比无
collation版本大 10–30%,因为要存储归一化后的排序键 - 写入性能下降更明显——每次插入/更新都要执行 collation 规则计算,尤其当字段内容长或 locale 复杂(如中文、阿拉伯语)时
- 某些驱动(如早期 PyMongo)默认不传递
collation参数,需显式设置,否则查询走全表扫描 - 在分片集群中,
collation必须在所有分片上一致,否则路由可能出错;片键字段若为字符串,强烈建议其索引也带相同collation
真正要用好它,得同时管住建索引、写查询、选驱动、压数据这四头——漏掉任何一头,都可能让“不区分大小写”变成“查不到”。

















