ElasticSearch:第一章 集群入门

什么是 ElasticSearch

索引

索引(index)是 ElasticSearch 存放数据的地方。如果你熟悉关系型数据库,就可以将索引理解为关系型数据库中的一张表。

文档

文档(document)是 ElasticSearch 中存储的主要实体。类比关系型数据库,ElasticSearch 中的文档相当于关系型数据库中的一行数据。

ElasticSearch 的文档也可以具有不同的结构,但 ElasticSearch 要求公用字段具有相同类型

文档由字段组成,ElasticSearch 允许一个字段出现多次,该类字段被称为多值字段(multivalued)。每个字段对应一种类型。ElasticSearch 可以自动确定字段类型,也可以通过模式映射(schema mapping)定义文档结构。

文档类型

在 ElasticSearch 中,一个索引可以存储多个不同用途的对象。文档类型可以帮助我们区分这些对象。每个文档可以有不同的结构。不同的文档对同一字段不能设置为不同的文档类型。

节点和集群

节点(node)是 ElasticSearch 的基本组成单元,一个节点就是一个 ElasticSearch 实例。

集群(cluster)是多个节点组成的集合,这些节点共同对外提供服务。

分片

分片(shard)是 ElasticSearch 的基本存储单位。一个索引可以存储大量数据,而一台机器的内存可能无法容纳所有数据,因此 ElasticSearch 将索引切分为多个分片,分布在集群中的不同节点上。

副本

副本(replica)是分片的拷贝。副本的作用是增加可用性,在集群中某个节点宕机后,副本可以提升为主节点继续提供服务。

对索引的所有修改操作都直接作用在主分片上,每个主分片可以有零个或多个副本分片。当主分片丢失时,集群会选择一个副本分片提升为主分片。

配置

所有配置文件都位于 config 目录下。该目录下有 elasticsearch.ymllogging.yml 两个文件。elasticsearch.yml 文件是 ElasticSearch 的配置文件,logging.yml 是日志的配置文件。

  • elasticsearch.yml

    • cluster.name:集群名称,默认是 elasticsearch

    • node.name:节点名称,默认是随机生成的。

  • loggging.yml

    定义了日志的级别和输出位置。仅当在需要适配监视环境或备份解决方案,抑或在系统调试时才有必要去修改日志的配置。

在索引过程中,尤其是有很多分片和副本时,ElasticSearch 会创建若干文件。因此,操作系统对打开文件数量的限制不能少于 32000。对于 Linux 服务区,需要修改 /etc/security/limits.conf 文件,并且可以通过 ulimit 命令查看修改后的结果。

核心字段类型

  • 字符串类型
  • 数值类型
  • 日期类型
  • 布尔类型
  • 二进制类型

通用属性

  • index_name:存储在索引中的字段名称。
  • index:该属性的取值为 analyzedno,字符串型的字段还可设为 not_analyzed。如果设置为 analyzed 类型,则该字段将会被索引,因而是可搜索的;如果设置为 no,则该字段不可被搜索。默认值是 analyzed。字符串类型的字段设为 not_analyzed 时,该字段会被索引但不需要分析。因此,该字段会按原样写入索引,只有完全匹配的搜索才能查到该字段。
  • store:该属性的取值为 yesno,默认值是 no。如果设置为 yes,则该字段的原始值会存储在索引中;如果设置为 no,意味着不能在结果中返回字段的原始值(即使没有存储原始值,也可以使用 _source 字段返回原始值)。
  • boost:该属性的取值为一个浮点数,默认值是 1.0。用于设置该字段的权重,该字段的权重越高,在搜索结果中就越靠前。
  • null_value:该属性的取值可以是任何字符串,默认值是 null。如果该字段的值为 null,则使用该属性指定的值替代。
  • include_in_all:该属性的取值为 truefalse,默认值是 true。如果启用 _all 字段则包含所有的字段。

字符串类型

  • term_vector:该属性的取值为 nowith_positionswith_offsetswith_positions_offsets,默认值是 no。该属性用于设置是否存储字段的 Lucene 词向量 (term vector),如果设置为 no,则不存储;如果设置为 with_positions,则存储词的位置;如果设置为 with_offsets,则存储词的偏移量;如果设置为 with_positions_offsets,则同时存储词的位置和偏移量。
  • omit_norms:该属性的取值为 truefalse,默认值是 false。如果设置为 true,则不存储字段的 norms 信息,此时不能使用索引时加权。
  • omit_term_freq_and_positions:该属性的取值为 truefalse,默认值是 false。如果设置为 true,则不存储词频和位置信息(从 ElaticSearch 2.0 开始,该属性已弃用)。
  • index_options:该属性的取值为 docsfreqspositions,默认值是 freqs。如果设置为 docs,则只索引文档数量;如果设置为 freqs,则索引文档数量和词频;如果设置为 positions,则索引文档数量、词频和词的位置。
  • anaylzer:该属性的取值是分析器名称,默认值是 standard
  • index_analyzer:该属性的取值是用于索引的分析器名称,默认值是 standard
  • searh_analyzer:该属性的取值是用于搜索的分析器名称,默认值是 standard
  • ignore_above:该属性的取值是一个整数,默认值是 2147483647。如果字段的长度超过该属性指定的值,则会被忽略。如果只关心该字段的前 N 个字符,则可以使用该属性。

数值类型

  • precision_step:该属性的取值是一个整数,默认值是 1。该属性用于设置数值类型字段的分段步长。值越低则生成的分段数越多,进行 range 查询时就越快(但索引也会变大)。
  • ignore_malformed:该属性的取值为 truefalse,默认值是 false。如果设置为 true,则忽略该字段的格式错误;

日期类型

  • format:该属性的取值是日期格式化字符串,默认值是 dateOptionalTime
  • precision_step
  • ignore_malformed

布尔类型

可取值为 truefalse

二进制类型

二进制字段是指用 base64 编码的二进制数据,可以用于存储图片、文档等。默认情况下,ElasticSearch 不会对二进制字段进行索引。二进制类型只支持 index_name 属性。

multi_field 类型

multi_field 类型允许将多个核心类型映射到同一个字段,并且进行不同的分析。

分析器

分析器(analyzer)是 ElasticSearch 中用于对字符串进行分词的组件。

ElasticSearch 提供了多种内置的分析器,也可以自定义分析器。

内置分析器

  • standard:标准分析器,默认的分析器。
  • simple:简单分析器,以非字母字符作为分界点。
  • whitespace:空白分析器,以空白符作为分界点。
  • stop:停用词分析器,移除停用词。
  • keyword:关键字分析器,不做任何分析。

自定义分析器

{
  "settings": {
    "analysis": {
      "filter": {
        "my_stopwords": {
          "type": "stop",
          "stopwords": ["the"]
        }
      },
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "standard",
          "filter": ["lowercase", "my_stopwords"]
        }
      }
    }
  }
}
  

_analyzer 字段

_analyzer 字段用来指定一个字段值,该值可以用于作为解析该字段所属文档的分析器的名称。

_all 字段

_all 字段是 ElasticSearch 中默认的字段,用于搜索所有字段。

_all 字段默认是启用的,但也可以将其禁用。

_all 字段会增加索引的大小,因此如果不需要搜索所有字段,最好禁用该字段。

动态映射和模板

ElasticSearch 允许根据文档自动创建索引和映射。

ElasticSearch 会根据文档的 JSON 格式自动创建字段并设置默认的映射类型。可以通过将 dynamic 设置为 false 来禁用自动添加字段。

动态模板

动态模板是 ElasticSearch 中用于定义字段映射类型的规则的配置文件。

  • 匹配模式

    • match:匹配字段名称,模板会被使用。
    • unmatch:不匹配字段名称,模板会被使用。
  • 可使用变量

    • {name}:输入文档中原始字段的名称。
    • {dynamic_type}:从原始文档确定的类型。
  • ElasticSearch 根据定义的顺序来检查模板,并应用第一个匹配的模板。最通用的模板(如带有 "match": "*" 的模板)放在最后。

索引模板

  • 每个模板定义了一个模式,用于匹配索引名称。
  • 如果匹配,模板中定义的取值被复制到索引的映射中。
  • 如果有多个模板匹配,则取值会合并,并且后应用模板的取值会覆盖先应用的取值。
  • 可以通过 order 属性控制模板的预期使用顺序。
  • 模板也可以存储到文件中。默认放在 config/templates 目录下。此时,文件名必须以 .json 结尾,文件名就是模板的名称,并且 JSON 文件中要以模板名称作为的主对象的键。另外,该模板必须放置在 ElasticSearch 的每个实例中。这些文件中定义的模板不能通过 REST API 调用。

路由选择

路由选择允许我们选择一个分片以用于索引和搜索数据。

当有个文档需要索引时,在索引操作过程中,ElasticSearch 会根据文档的 _id 计算该文档应该存储在哪个分片上。默认情况下,ElasticSearch 使用文档的 _id 哈希值对分片数量取模,基于该值将文档存储到某个可用的主分片中。然后,ElasticSearch 会将该文档复制到所有相关的副本分片中。

搜索有点不同于索引,因为在大多数情况下,你需要询问所有的分片以得到感兴趣的数据。

路由选择用来控制你的文档和查询被转发到哪个分片。在 ElasticSearch 索引和查询时都可以指定路由值。

提供路由值最简单的方法是使用 routing 参数。

curl -XPUT "localhost:9200/my_index/_doc?routing=12" -d'{
  "id": "1",
  "title": "My first blog post",
  "content": "This is my first blog post.",
  "userId": 12
}
  
curl -XGET "localhost:9200/my_index/_search?routing=12&q=userId:12"
  

ElasticSearch 允许我们定义一个字段,该字段的取值被用作索引时的路由值。

"_routing": {
  "required": true,
  "path": "userId"
}
  

上述定义意味着需要提供路由值,否则索引请求会失败。

索引别名

索引别名允许我们使用一个名称来引用一组索引。

索引别名可以让我们在索引之间进行切换,而不需要修改客户端代码。

curl -XPOST "localhost:9200/_aliases" -d'{
  "actions": [
    {"add": {"index": "my_index", "alias": "my_alias"}},
    {"remove": {"index": "my_old_index", "alias": "my_alias"}}
  ]
}
  

别名中支持过滤和路由选择。

curl -XPOST "localhost:9200/_aliases" -d'{
  "actions": [
    {
      "add": {
        "index": "my_index", 
        "alias": "my_alias",
        "filter": { "term": { "userId": "12" } },
        "index_routing": "12,13,14",
        "search_routing": "12"
      }
    }
  ]
}'