中间件-elastic

analysis

分析器 analyzer

elastic中通过analyzer生成分词,analyzer由字符过滤器、分词器、分词过滤器组成,生成分词的过程也是输入文本经过analyzer的各个组件过程;

首先文本先经过字符过滤器,进行字符的过滤、修改、替换,得到新的字符文本进入到分词器生成分词,生成的分词再经过分词过滤器处理掉一些没有作用的分词,最终得到输入文本的分词结果。

standard

  • 如果不指定分析器,则默认使用标准分析器。它提供基于语法的分词器(基于Unicode文本分隔算法)且对于大部分语言都适用。
组件
  • Tokenizer(分词器)
    • Standard Tokenizer(标准分词器)
  • Token Filters(分词过滤器)
    • Standard Token Filter(标准分词过滤器)
    • Lower Case Token Filter(小写分词过滤器)
    • Stop Token Filter(停词分词过滤器,默认禁用)
配置
参数说明
max_token_length最大分词长度,如果分词长度超过了这个长度,它会以max_token_length的间隔分割。
stopwords预定义的停词,比如_english_或者是包含一系列停词的数组。默认是_none_
stopwords_path包含停词的文件的路径

Fingerprint

  • 指纹分析器:实现了fingerprinting algorithm,该算法在OpenRefine项目中使用,以辅助聚类。
  • 输入本文转化为小写,规范化以移除扩展字符,排序,删除重复数据,连接成单个分词。如果配置了停词列表,停词也会被删除。
组件
  • 分词器
    • Standard Tokenizer
  • 分词过滤器
    • Lower Case Token Filter
    • ASCII Folding Token Filter
    • Stop Token Filter(默认关闭)
    • Fingerprint Token Filter
配置
参数说明
separator用来接连分词的字符。默认是空格
max_output_size分词最大的长度。默认是255。长度大于该值的分词会被丢弃。
stopwords预定义的停词,比如_english_,或者是包含停词的列表。默认是_none_
stopwords_path停词文件的路径

simple

  • 简单分析器在非字母字符处将文本拆分为分词。所有分词转化为小写字母。
组件
  • 分词器
    • Lower Case Tokenizer

whitespace

  • 空白符分析器在空白符处将文本拆分为分词。
组件
  • 分词器
    • Whitespace Tokenizer

stop

  • 停词分析器和简单分析器一样,但是它支持删除停词。默认使用_english_停词。
组件
  • 分词器
    • Lower Case Tokenizer
  • 分词过滤器
    • Stop Token Filter
配置
参数说明
stopwords预定义的停词比如_english_,或者包含一系列停词的数组。默认是_english_
stopwords_path停词文件的路径

pattern

  • 模式分析器使用正则表达式对文本进行分词。注意正则表达式匹配的是分隔符而不是分词本身。正则表达式默认是\W+(所有非单词字符)。
组件
  • 分词器
    • Pattern Tokenizer
  • 分词过滤器
    • Lower Case Token Filter
    • Stop Token Filter(默认禁用)
参数说明
patternJava正则表达式,默认是\W+
flagsJava正则表达式标志。标志通过通道符号分隔,如"CASE_INSENSITIVE
lowercase分词是否转化为小写。默认为true
stopwords预定义的停词列表,比如_english_或者是包含一系列停词的数组。默认是_none_
stopwords_path停词文件的路径

自定义分析器

当内建的分析器无法满足需要时,可以创建一个自定义的分析器,包含以下内容:

  • 0个或多个字符过滤器
  • 1个分词器
  • 0个或多个分词过滤器

自定义的分析器接受以下参数:

参数说明
tokenizer内建或自定义的分词器(必须)
char_filter内建或自定义的字符过滤器数组(可选)
filter内建或自定义的分词过滤器数组(可选)
position_increment_gap当索引一个文本数组时,Elasticsearch在一个数组的最后一个分词和下一个数组的第一个分词之间插入一个伪间隔,以保证短语查询不会匹配到不同数组元素中的两个分词。默认是100
实例

该示例组合以下的组件:

  • 字符过滤器
    • HTML Strip Character Filter
  • 分词器
    • Standard Tokenizer
  • 分词过滤器
    • Lowercase Token Filter
    • ASCII-Folding Token Filter
curl -XPUT 'localhost:9200/my_index?pretty' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type":      "custom",
          "tokenizer": "standard",
          "char_filter": [
            "html_strip"
          ],
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  }
}
'

字符过滤器 Character Filter

分词过滤器 Token Filter

分词器 Tokenizer

classic(经典分词器):

说明
  • 英文友好分词器,多非英语文本不适用;
  • 在大多数标点符号上分割文本;
  • . 符号后没有空格时不分割;
  • -符号后是数字时不分割;
  • email地址和网络主机名;
配置
  • max_token_length:最大的分词长度。如果分词长度超过了最大长度,则以最大长度为间隔分割分词。默认是255

Edge N-Gram(前缀片段分词器):

说明
  • 根据参数指定的字符列表对文本进行分割,然后根据gram参数对每个分割结果前缀分割生成分词
  • 例如:Quick的分词结果:Q、Qu

默认的gram长度几乎完全无用。使用edge_ngram前必须先配置。

配置
参数说明
min_gram字符最小长度。默认是1
max_gram字符最大长度。默认是2
token_chars包含在分词中的字符类。Elasticsearch会在不属于该分类的字符处分割文本。默认是[](保留所有字符)

字符类可以是以下的任意一种

  • letter—— a, b, ï,
  • digit—— 3, 7
  • whitespace——" ", "\n"
  • punctuation——!, "
  • symbol——$,

keyword(关键字分词器):

说明
  • 空分词器,接受任意的输入,将相同的文本以单个分词输出;
  • 它可以和分词过滤器结合来规范化输出,比如将email地址转化为小写;
配置
参数说明
buffer_size单次传递中,读入分词缓存的字符数量。默认是256。分词缓存会按该大小增长直到所有的文本都被消耗。建议不用改变这个设置。

letter(字母分词器)

说明
  • 在非字母处分割文本
配置

lowercase(小写分词器)

说明
  • 小写分词器和字母分词器一样,在非字母处分割文本,但是小写分词器将所有的分词转化为小写;
  • 功能上等价于字母分词器和小写分词过滤器的组合,但是效率更高因为它在一个步骤中执行这两步。
配置

NGram(片段分词器)

说明
  • 根据配置的字符表对不属于该字符表的字符处进行分割文本,然后针对每个单词产生指定长度的N-gram
  • N-gram是一个在单词上移动的滑动窗口(指定长度的连续字符序列);
  • 它们对于查询不使用空格的语言或德语这样有长复合词的语言很有用;
  • 默认设置下,ngram分词器将原始文本视为单个分词,使用最小长度1和最大长度2来生成N-gram。例如:Quick : [Q, Qu, u, ui, i, ic, c, ck, k]
配置
参数说明
min_gram字符最小长度。默认是1
max_gram字符最大长度。默认是2
token_chars包含在分词中的字符类。Elasticsearch会在不属于该分类的字符处分割文本。默认是[](保留所有字符)

字符类可以是以下的任意一种

  • letter—— a, b, ï,
  • digit—— 3, 7
  • whitespace——" ", "\n"
  • punctuation——!, "
  • symbol——$,

min_grammax_gram设置为同一个值通常是有意义的。长度越小,匹配的文档越多但是匹配的质量越差;长度越长,匹配得越详细。通常tri-gram(长度为3)是一个比较好的值。

path_hierarchy(层级分词器)

说明
  • 路径、层级、目录分词器,生成各个层级到根的路径分词
配置
参数说明
delimiter作为路径分隔符的字符。默认是/
replacement用作分隔符的可选替换字符,默认为delimiter。如:root-etc 生成 、/root/etc
buffer_size单次传递中,读入分词缓存的字符数量。默认是1024。分词缓存会按该大小增长直到所有的文本都被消耗。建议不用改变这个设置。
reverse如果设置为true,逆转分词的顺序。默认是false
skip跳过初始分词的数量。默认是0

pattern(正则分词器):

说明
  • 使用正则表达式将文本分割为分词,当遇见匹配的单词分隔符,或者捕获匹配的文本作为分词。
  • 默认的模式是\W+,在非单词字符处分割文本。
  • 防止病态的正则表达式。模式分析器使用Java Regular Expressions。糟糕的正则表达式书写会造成运行缓慢甚至栈溢出错误,导致正在运行的节点突然退出。
配置
参数说明
patternJava正则表达式,默认是\W+
flagsJava正则表达式标识。以管道符(
group哪个捕获的组提取为分词。默认是-1

standard(标准分词器):

说明
  • 标准分词器提供基于语法的词汇切分(基于Unicode文本分割算法),适用于大部分语言。
配置
参数说明
max_token_length最大的分词长度。如果分词长度超过了最大长度,则以最大长度为间隔分割分词。默认是255

thai:

说明
  • 用于泰语,并使用内置的泰语分段算法.
配置

uax-url-email(url-email分词器):

说明
  • 标准分词器的增强,同时URLs和email地址,将它们作为一个单独的分词
配置
参数说明
max_token_length最大的分词长度。如果分词长度超过了最大长度,则以最大长度为间隔分割分词。默认是255

whitespace(空格分词器):

说明
  • 空白符分词器在空白符处分割文本。
配置

映射mapping

映射用来定义文档和文档中的字段如何存储、索引。使用映射定义:

  • 哪个string字段应该被当做全文字段
  • 哪个字段包含数字、日期、地理位置
  • 文档中所有的字段值是否应该被_all字段索引
  • 日期的格式
  • 控制动态增加字段的自定义规则

防止映射爆炸(mappings explosion)

下面的设置允许你限制手动或者自动可以创建的字段映射的数量,以防止坏的文档引起映射爆炸。

  • index.mapping.total_fields.limit
    • 一个索引最大的字段数量。默认值是1000
  • index.mapping.depth.limit
    • 字段最大的深度,深度指的是内部对象的数量。比如,如果所有的字段都定义在根对象层级上,那么深度是1;如果有一个对象映射,那么深度是2。默认值是20
  • index.mapping.nested_fields.limit
    • 索引中nested字段最大的数量。将1个文档用100个嵌套字段来索引,实际上索引了101个文档,因为每个嵌套的文档都被当做一个单独的隐藏文档来索引。

更新已存在的映射

除了记录在哪里,已存在的类型映射和字段映射 不能被更新。更改映射意味着所有已经被索引的文档都会失效。所以,你必须创建一个新的索引然后将数据重新建立索引。

动态映射

Elasticsearch一个最重要的特征是它可以让你尽快地开始探索数据而不用过多地关注其他。你不用为了索引文档而在一开始创建索引、定义映射类型、定义字段,你只需要建立一个文档索引,索引、类型、字段会自动生成。

自定检测添加新类型和字段的功能叫动态映射。动态映射的规则可以根据需求来自定义:

  • _default_映射

    • 配置新类型使用的基本映射
  • 动态字段映射

    • 控制动态字段检测的规则
  • 动态模板

    • 自定义规则来配置动态增加字段的映射

index templates允许你设置新索引默认的映射、配置、别名,不论新索引是自动创建还是显式创建的

关闭自动创建类型

设置index.mapper.dynamicfalse可以关闭某个索引上自动类型创建。

curl -XPUT 'localhost:9200/data/_settings?pretty' -d'
{
  "index.mapper.dynamic":false // 1
}'
  • 1 关闭索引data上自动类型创建

字段数据类型

数组类型

Elasticsearch中没有专用的array类型。任何类型默认都可以包含0个或多个值,但是数组中的值必须是同一类型的。比如:

  • 字符串数组:[“one”, “two”]
  • 整形数组:[1, 2]
  • 包含数组的数组:[1, [2, 3]],等价于[1, 2, 3]
  • 对象的数组:[{“name”:“Mary”, “age”:12}, {“name”:“John”, “age”:10}]

对象数组的工作方式和你预期的不一样:不能单独查询数组中的每个对象。如果你需要这样查询必须使用nested类型而不是object类型。更详细的解释参照Nested datatype

动态增加字段时,数组中第一个值决定了字段的类型。数组中其他的值必须和这个类型相同或者至少可以强制转化成一致的类型。

不支持包含混合数据类型的数组:[10, “some string”]

包含null值的数组,null值可以被null_value替换或者整个数组跳过。空数组[]作为缺失的字段——没有值的字段。