Elasticsearch NEST AutoMap配置字符串大小写不敏感搜索报错解决
异常原因
运行抛出Sequence contains no elements是因为你在配置属性映射时写的.Name(n => n)是无效表达式,没有指向实体的任何具体属性,NEST反射解析映射规则时找不到匹配属性,直接抛出该异常。同时你当前手动配置Text属性的写法仅能对单个指定字段生效,无法给AutoMap生成的所有字符串字段统一追加配置,不符合全局生效的需求。
正确实现方案
你的需求是不改动现有基于keyword字段的搜索逻辑,不需要额外新增keyword_lowercase子字段,直接给AutoMap默认生成的keyword子字段绑定lowercase normalizer即可,所有原有查询逻辑完全不用调整,就能实现大小写不敏感搜索。
完整可运行代码如下:
public void CheckIndexes(IServiceCollection services) { var sp = services.BuildServiceProvider(); var elastiClient = sp.GetService<ElasticSearchClient>(); foreach (var index in Indexes.List) { if (!elastiClient.Client.Indices.Exists(index.IndexName).Exists) { elastiClient.Client.Indices.Create(index.IndexName, c => c .Settings(s => s .NumberOfShards(1) .NumberOfReplicas(0) .Analysis(a => a .Normalizers(n => n // 注意不要用lowercase作为自定义normalizer名称,避免和内置组件重名冲突 .Custom("lowercase_normalizer", cn => cn .Filters("lowercase") ) ) ) ) .Map<BaseEntity>(m => m .AutoMap(index.EntityType) .Properties(p => { // 读取AutoMap自动生成的所有属性映射 var autoMappedProps = m.AutoMap(index.EntityType).Properties; foreach (var prop in autoMappedProps) { // 仅处理字符串类型生成的text字段 if (prop is ITextProperty textProp && textProp.Fields != null) { // 给默认生成的keyword子字段绑定lowercase normalizer foreach (var subField in textProp.Fields) { if (subField is IKeywordProperty keywordSubField && keywordSubField.Name == "keyword") { keywordSubField.Normalizer = "lowercase_normalizer"; } } } p.Add(prop); } return p; }) ) ); } } }
这个方案完全不需要改动现有业务搜索逻辑,所有查询仍然走原来的{字段名}.keyword路径,只是写入和查询时会自动通过normalizer把文本转成小写匹配,天然实现大小写不敏感。
注意事项
- 映射配置仅在索引新建时生效,已经创建过的旧索引需要删除重建,或者执行关闭索引、更新映射、重新打开索引的操作才能生效。
- normalizer的修改不会对已存在的存量文档自动生效,需要重新全量导入数据,才能让所有历史数据支持大小写不敏感搜索。
- 如果你需要保留原始区分大小写的精确匹配能力,只需要在遍历子字段的逻辑里,额外新增一个不带normalizer的keyword子字段即可。
内容的提问来源于stack exchange,提问作者ErvinsA
相关产品推荐
相关产品推荐

