Mongo Atlas Search如何实现大小写不敏感的部分匹配查询?
解决Mongo Atlas Search同时支持大小写不敏感与部分匹配的方案
你的需求完全可以实现,之前的方向没有错误,只需调整索引配置和查询逻辑即可达成目标。
问题根源
当前使用的lucene.keyword分析器会将整个字段作为单个token,因此wildcard查询能实现部分匹配,但它不会做大小写转换,导致查询大小写敏感;而lucene.standard分析器虽支持大小写不敏感,但会将文本拆分为多个token,wildcard查询只能匹配单个token的部分内容,无法实现跨token或整个字段的任意位置部分匹配。
正确实现方案
1. 调整索引配置:使用自定义分析器
创建同时支持大小写转换和保留整字段为单个token的自定义分析器,兼顾大小写不敏感与部分匹配的需求。替换原search_organizations_name索引的配置:
{ "name": { "type": "string", "analyzer": { "type": "custom", "tokenizer": "keyword", "filter": ["lowercase"] }, "searchAnalyzer": { "type": "custom", "tokenizer": "keyword", "filter": ["lowercase"] } } }
该分析器通过keyword分词器保留整字段为单个token,再通过lowercase过滤器统一转换为小写,索引时会将Organisation存储为organisation,查询时也会把输入的ORG转为org,实现大小写不敏感。
2. 调整查询代码
保留wildcard逻辑,新增allowAnalyzedField参数(允许在经过分析的字段上使用wildcard查询),同时可提前将查询文本转小写(增强兼容性):
func (r *Repo) Search(ctx context.Context, query string) ([]Organization, error) { querySplit := strings.Split(strings.ToLower(query), " ") // 为每个查询词添加通配符 for i := range querySplit { querySplit[i] = fmt.Sprintf("*%s*", querySplit[i]) } // 定义聚合搜索阶段 searchStage := bson.D{ {"$search", bson.D{ {"index", "search_organizations_name"}, {"wildcard", bson.D{ {"path", "name"}, {"query", querySplit}, {"allowAnalyzedField", true} // 必须开启,支持在分析字段上执行wildcard查询 }}, }}, } // 执行聚合查询 cursor, err := r.organizationsCollection().Aggregate(ctx, mongo.Pipeline{searchStage}) if err != nil { return nil, err // 按实际业务逻辑处理错误 } var orgs []Organization if err = cursor.All(ctx, &orgs); err != nil { return nil, errors.Wrap(err, "parsing organizations to return") } return orgs, nil }
效果验证
- 输入
org可匹配Organisation、ORGANIZATION、my-org等包含org(大小写无关)的内容 - 输入
Org或ORG会自动转为小写,匹配相同结果 - 多词查询如
big org可匹配同时包含big和org的组织名称
备选方案:autocomplete算子(适合前缀/中缀补全场景)
如果你的部分匹配需求以前缀/中缀补全为主,可使用autocomplete算子,性能比wildcard更优:
索引配置:
{ "name": { "type": "autocomplete", "analyzer": "lucene.simple", "tokenizer": "keyword" } }
查询代码:
searchStage := bson.D{ {"$search", bson.D{ {"index", "search_organizations_name"}, {"autocomplete", bson.D{ {"path", "name"}, {"query", strings.ToLower(query)}, {"fuzzy", bson.D{{"maxEdits", 1}}} // 可选,支持模糊匹配 }}, }}, }
内容的提问来源于stack exchange,提问作者Ido Van Orell
相关产品推荐
相关产品推荐

