• ES系列六、ES字段类型及ES内置analyzer分析


    一、背景知识

    在Es中,字段的类型很关键:

    • 在索引的时候,如果字段第一次出现,会自动识别某个类型,这种规则之前已经讲过了。
    • 那么如果一个字段已经存在了,并且设置为某个类型。再来一条数据,字段的数据不与当前的类型相符,就会出现字段冲突的问题。如果发生了冲突,在2.x版本会自动拒绝。
    • 如果自动映射无法满足需求,就需要使用者自己来设置映射类型,因此,就需要使用者了解ES中的类型。

    下面就步入正题吧!

    二、字段中的索引和存储

    其中需要说明的是:

    1.index定义字段的分析类型以及检索方式

    • 如果是no,则无法通过检索查询到该字段;
    • 如果设置为not_analyzed则会将整个字段存储为关键词,常用于汉字短语、邮箱等复杂的字符串;
    • 如果设置为analyzed则将会通过默认的standard分析器进行分析,详细的分析规则参考这里

    2.store定义了字段是否存储

    在《ES IN ACTION》中有这样一段描述:

    This might be useful when you ask Elasticsearch for a particular field because retrieving a single stored field will be faster than retrieving the entire _source and extracting that field from it, especially when you have large documents.
    NOTE When you store individual fields as well, you should take into account that the more you store, the bigger your index gets. Usually bigger indices imply slower indexing and slower searching.

    意思是,在ES中原始的文本会存储在_source里面(除非你关闭了它)。默认情况下其他提取出来的字段都不是独立存储的,是从_source里面提取出来的。当然你也可以独立的存储某个字段,只要设置store:true即可。

    独立存储某个字段,在频繁使用某个特殊字段时很常用。而且获取独立存储的字段要比从_source中解析快得多,而且额外你还需要从_source中解析出来这个字段,尤其是_source特别大的时候。

    不过需要注意的是,独立存储的字段越多,那么索引就越大;索引越大,索引和检索的过程就会越慢....

    3.Text vs. keyword

    ElasticSearch 5.0以后,string类型有重大变更,移除了string类型,string字段被拆分成两种新的数据类型: text用于全文搜索的,而keyword用于关键词搜索。

    ElasticSearch对字符串拥有两种完全不同的搜索方式. 你可以按照整个文本进行匹配, 即关键词搜索(keyword search), 也可以按单个字符匹配, 即全文搜索(full-text search). 对ElasticSearch稍有了解的人都知道, 前者的字符串被称为not-analyzed字符, 而后者被称作analyzed字符串。

    Text:会分词,然后进行索引

           支持模糊、精确查询

           不支持聚合

    keyword:不进行分词,直接索引

           支持模糊、精确查询

           支持聚合

    text用于全文搜索的, 而keyword用于关键词搜索.

    如果想做类似于sql中的like查询,可定义为keyword并使用通配符wildcard方式查询。

    ElasticSearch字符串将默认被同时映射成textkeyword类型,将会自动创建下面的动态映射(dynamic mappings):

    {
        "foo": {
            "type": "text",
            "fields": {
                "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                }
            }
        }
    }

    基于这个映射你即可以在foo字段上进行全文搜索, 也可以通过foo.keyword字段实现关键词搜索及数据聚合.

    禁用这个特性也很方便: 你只需要在定义mapping时显式声明字符串字段的类型或者使用一个动态模板(dynamic template)来匹配你所有的字符串字段即可. 例如通过下面的dynamic template就可以恢复到在ElasticSearch 2.x中使用的dynamic template的效果:

    {
    "match_mapping_type": "string",
    "mapping": {
    "type": "text"
    }
    }

    4.Numeric

    数值类型,注意numeric并不是一个类型,它包括多种类型,比如:long,integer,short,byte,double,float,每种的存储空间都是不一样的,一般默认推荐integer和float。官方文档参考

    重要的参数:

    index分析
    • not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
    • no
    store存储
    • true 独立存储
    • false(默认)不存储,从_source中解析

    5.date

    日期类型,该类型可以接受一些常见的日期表达方式,官方文档参考

    重要的参数:

    index分析
    • not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
    • no
    store存储
    • true 独立存储
    • false(默认)不存储,从_source中解析
    format格式化
    • strict_date_optional_time||epoch_millis(默认)
    • 你也可以自定义格式化内容,比如
    "date": {
      "type":   "date",
      "format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
    }

    6.IP

    这个类型可以用来标识IPV4的地址,参考官方文档

    常用参数:

    index分析
    • not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
    • no
    store存储
    • true 独立存储
    • false(默认)不存储,从_source中解析

    7.boolean

    布尔类型,所有的类型都可以标识布尔类型,参考官方文档

    • False: 表示该值的有:false, "false", "off", "no", "0", "" (empty string), 0, 0.0
    • True: 所有非False的都是true

    重要的参数:

    index分析
    • not_analyzed(默认) ,设置为该值可以保证该字段能通过检索查询到
    • no
    store存储
    • true 独立存储
    • false(默认)不存储,从_source中解析

    三、内置分词器

    1.基本概念

    全文搜索引擎会用某种算法对要建索引的文档进行分析, 从文档中提取出若干Token(词元), 这些算法称为Tokenizer(分词器), 这些Token会被进一步处理, 比如转成小写等, 这些处理算法被称为Token Filter(词元处理器), 被处理后的结果被称为Term(词), 文档中包含了几个这样的Term被称为Frequency(词频)。 引擎会建立Term和原文档的Inverted Index(倒排索引), 这样就能根据Term很快到找到源文档了。 文本被Tokenizer处理前可能要做一些预处理, 比如去掉里面的HTML标记, 这些处理的算法被称为Character Filter(字符过滤器), 这整个的分析算法被称为Analyzer(分析器)。

    ES内置了很多Analyzer, 还有很多第三方的Analyzer插件, 比如一些处理中文的Analyzer(中文分词)。

    analyzer、 tokenizer、 filter可以在elasticsearch.yml 配置, 下面是配置例子

    index :
        analysis :
            analyzer :
                standard :
                    type : standard
                    stopwords : [stop1, stop2]
                myAnalyzer1 :
                    type : standard
                    stopwords : [stop1, stop2, stop3]
                    max_token_length : 500
                # configure a custom analyzer which is
                # exactly like the default standard analyzer
                myAnalyzer2 :
                    tokenizer : standard
                    filter : [standard, lowercase, stop]
            tokenizer :
                myTokenizer1 :
                    type : standard
                    max_token_length : 900
                myTokenizer2 :
                    type : keyword
                    buffer_size : 512
            filter :
                myTokenFilter1 :
                    type : stop
                    stopwords : [stop1, stop2, stop3, stop4]
                myTokenFilter2 :
                    type : length
                    min : 0
                    max : 2000

    2.组装自己的analyzer

    ES内置若干analyzer, 另外还可以用内置的character filter, tokenizer, token filter组装一个analyzer(custom analyzer), 比如

    index :
        analysis :
            analyzer :
                myAnalyzer :
                    tokenizer : standard
                    filter : [standard, lowercase, stop]

    3.使用第三方分词器

    如果你要使用第三方的analyzer插件,需要先在配置文件elasticsearch.yml中注册, 下面是配置IkAnalyzer的例子

    index:
      analysis:
        analyzer:      
          ik:
              alias: [ik_analyzer]
              type: org.elasticsearch.index.analysis.IkAnalyzerProvider

    当一个analyzer在配置文件中被注册到一个名字(logical name)下后,在mapping定义或者一些API里就可以用这个名字来引用该analyzer了,比如

    "message": {
        "type": "string",
        "indexAnalyzer": "ik",
        "searchAnalyzer": "ik"
    }

    4.配置默认分词器

    如果没有指定索引和搜索用的analyzer,ES会用默认的analyzer来处理,也就是名字(logical name)为defaultdefault_indexdefault_search的analyzer。 从名字可以看出来,default是索引和搜索时用的默认的analyzer,default_index是索引时用的默认的analyzer, default_search是查询时用的默认analyzer。

    下面是在elasticsearch.yml中配置默认analyzer的例子

    index:
      analysis:
        analyzer:
            default_index:
                tokenizer: standard
                filter: [standard, lowercase, my_synonym, my_snow]
            default_search:
                tokenizer: standard
                filter: [standard, lowercase, stop]

    或者用这种格式

    index.analysis.analyzer.default.type : "mmseg"

    一个analyzer可以起若干别名,比如在下面的例子中,standard analyzer可以用alias1或者alias2来引用

    index :
      analysis :
        analyzer。 :
          standard :
            alias: [alias1, alias2]
            type : standard
            stopwords : [test1, test2, test3]

    下面是内置的一些analyzer:

    analyzerlogical namedescription
    standard analyzer standard standard tokenizer, standard filter, lower case filter, stop filter
    simple analyzer simple lower case tokenizer
    stop analyzer stop lower case tokenizer, stop filter
    keyword analyzer keyword 不分词,内容整体作为一个token(not_analyzed)
    pattern analyzer whitespace 正则表达式分词,默认匹配W+
    language analyzers lang 各种语言
    snowball analyzer snowball standard tokenizer, standard filter, lower case filter, stop filter, snowball filter
    custom analyzer custom 一个Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter

    5.tokenizer

    ES内置的tokenizer列表。

    tokenizerlogical namedescription
    standard tokenizer standard  
    edge ngram tokenizer edgeNGram  
    keyword tokenizer keyword 不分词
    letter analyzer letter 按单词分
    lowercase analyzer lowercase letter tokenizer, lower case filter
    ngram analyzers nGram  
    whitespace analyzer whitespace 以空格为分隔符拆分
    pattern analyzer pattern 定义分隔符的正则表达式
    uax email url analyzer uax_url_email 不拆分url和email
    path hierarchy analyzer path_hierarchy 处理类似/path/to/somthing样式的字符串

    6.token filter

    ES内置的token filter列表。

    token filterlogical namedescription
    standard filter standard  
    ascii folding filter asciifolding  
    length filter length 去掉太长或者太短的
    lowercase filter lowercase 转成小写
    ngram filter nGram  
    edge ngram filter edgeNGram  
    porter stem filter porterStem 波特词干算法
    shingle filter shingle 定义分隔符的正则表达式
    stop filter stop 移除 stop words
    word delimiter filter word_delimiter 将一个单词再拆成子分词
    stemmer token filter stemmer  
    stemmer override filter stemmer_override  
    keyword marker filter keyword_marker  
    keyword repeat filter keyword_repeat  
    kstem filter kstem  
    snowball filter snowball  
    phonetic filter phonetic 插件
    synonym filter synonyms 处理同义词
    compound word filter dictionary_decompounder, hyphenation_decompounder 分解复合词
    reverse filter reverse 反转字符串
    elision filter elision 去掉缩略语
    truncate filter truncate 截断字符串
    unique filter unique  
    pattern capture filter pattern_capture  
    pattern replace filte pattern_replace 用正则表达式替换
    trim filter trim 去掉空格
    limit token count filter limit 限制token数量
    hunspell filter hunspell 拼写检查
    common grams filter common_grams  
    normalization filter arabic_normalization, persian_normalization  

    7.character filter

    ES内置的character filter列表

    character filterlogical namedescription
    mapping char filter mapping 根据配置的映射关系替换字符
    html strip char filter html_strip 去掉HTML元素
    pattern replace char filter pattern_replace 用正则表达式处理字符串
  • 相关阅读:
    cg数据类型
    线程和流的历史遗留
    流的总结及小问题

    集合练习
    集合属性的整理
    集合
    整理
    面向对象中知识的薄弱点
    自己的小问题和数组常用的方法
  • 原文地址:https://www.cnblogs.com/wangzhuxing/p/9502183.html
Copyright © 2020-2023  润新知