elasticsearch,使用normalizer优化keyword字段的查询

我们知道elasticsearch提供了很多的字段类型,当我们索引结构化的简单字段的时候可以使用keyword类型,例如id,email、主机名、状态码、标签、邮政编码等;

但是keyword字段类型在索引的时候,并不会对字段的值进行一些预处理,也就是直接保留字段的原值。

当我们使用如下文档进行索引的时候,es到底是怎样进行索引处理的呢?

 {
    "id":1,
    "name":"code"
}

 Es字段的索引是通过对应类型的mapper进行处理,通过KeywordFieldMapper的parseCreateField的396行可以看到索引的时候,es直接将name字段的value即”code”作为二进制保存,没有进行任何的处理。 

elasticsearch,使用normalizer优化keyword字段的查询_第1张图片

当我使用如下的查询语句进行查询的时候,es是怎么来构建查询语句的呢?

{
    "query":{
        
"term":{
            
"name":"code"
        }
    }

}

Es首先会获取name字段对应的字段类型,然后调用字段的termQuery来构建查询语句;

elasticsearch,使用normalizer优化keyword字段的查询_第2张图片

这里name字段对应的是KeywordFieldMapper,其并没有覆盖实现父类的的termQuery方法,所以直接执行父类TermBasedFieldType的对应方法,方法中使用indexedValueForSearch对查询关键字进行处理;

elasticsearch,使用normalizer优化keyword字段的查询_第3张图片

我们可以看到KeywordFieldMapper实现了indexedValueForSearch, 由于初始化的时候将search/index的Analyzer都设置为Lucene.KEYWORD_ANALYZER,所以这里会执行305行调用父类TermBasedFieldType的indexedValueForSearch。

elasticsearch,使用normalizer优化keyword字段的查询_第4张图片

我们可以看到父类TermBasedFieldType也未对value进行任何的处理;

elasticsearch,使用normalizer优化keyword字段的查询_第5张图片

这样会带来一个问题,如果字段对应的值并不是枚举类型,而是用户输入的标签等,如果用户输入的单词包含大小写,那么搜索的时候也必须输入一模一样的关键字,否则使用下边的查询语句是命中不了结果的;

{
    "query":{
        
"term":{
            
"name":"Code"
        }
    }

}

通过查询es的文档,我们可以看到keyword类型提供了一个normalizer的配置参数,可以在index之前进行一些预处理工作;在自定义的normalizer中可以定义character filters和token filters,这样我们可以像下边这样配置一个lowercase的token filters即可以实现忽略大小写。

{
    "settings":{
        
"analysis":{
            
"normalizer":{
                
"lowercase_normalizer":{
                    
"type":"custom",
                    
"filter":[
                        
"lowercase"
                    ]
                }
            }
        }
    },

    "mappings":{
        
"_doc":{
            
"properties":{
                
"id":{
                    
"type":"integer"
                },
                
"name":{
                    
"type":"keyword",
                    
"normalizer":"lowercase_normalizer"
                }
            }
        }
    }

} 

在CustomNormalizerProvider中我们可以看到解析配置的char filters和token filters,并组合生成Custome analyzer。

elasticsearch,使用normalizer优化keyword字段的查询_第6张图片

在生成name字段的mapper的时候,根据配置的normalizer name获取对象的对象,并设置为field type的normalizer和search analyzer。

elasticsearch,使用normalizer优化keyword字段的查询_第7张图片

当我们index下边的文档的时候,我们看下es是怎么处理的

{
    "id":1,
    "name":"Code"
}

可以看到index文档的时候,会获取keyword对应的field type的normalizer,然后对name字段的value进行处理。

elasticsearch,使用normalizer优化keyword字段的查询_第8张图片

当我们搜索的时候,由于已经重置了keyword 对应的field type的searchAnalyzer,所以会直接调用新的自定的normalizer的normalize对输入的关键字进行与处理。

elasticsearch,使用normalizer优化keyword字段的查询_第9张图片

最终不管我们输入的name的值大小写的形式怎样,我们都可以搜索到

elasticsearch,使用normalizer优化keyword字段的查询_第10张图片

 

 

 

你可能感兴趣的:(elasticsearch,elasticsearch,es,keyword,term,normalizer)