1. 流程

  1. 创建 Index(Settings & Mappings)
  2. 导入数据
  3. CRUD
  4. 索引别名

本教程基于Elasticsearch8.2版本

2. Start

1. Mapping

自定义 Mapping 有两种方法

  • 可以参考 API,纯手写
  • 为了减少输入的工作量,减少出错概率,可以依照以下步骤
    1. 创建一个临时的 Index,写入一些样本数据
    2. 通过 访问 Mapping API 获得该临时文件的动态 Mapping 定义
    3. 修改自动创建的 Mapping(比如自动推断的类型可能不正确等),使用该配置创建你的索引
    4. 删除临时索引

注意: Mapping 一旦定义,后续无法修改,所以一开始就要设置好。

能否更改 Mapping 的字段类型

新字段的自动检测和添加称为 动态映射

  • 两种情况

    • 新增加字段

      • Dynamic 设置为 true 时,一旦有新增字段的文档写入,Mapping 也同时被更新
      • Dynamic 设置为 false 时,Mapping 不会被更新,新增字段的数据无法被索引,但是信息会出现在_source字段中
      • Dynamic 设置为 Strict 时,文档写入会失败
    • 修改已有字段,一旦已经有数据写入,就不再支持修改字段定义

      • 因为 Lucene 实现的倒排索引,一旦生成后,就不允许修改

如果希望改变字段类型,必须调用 Reindex API,重建索引。

  • 新增加字段

    • Dynamic 设置为 true 时,一旦有新增字段的文档写入,Mapping 也同时被更新
    • Dynamic 设置为 false 时,Mapping 不会被更新,新增字段的数据无法被索引,但是信息会出现在_sourcez
    • Dynamic 设置为 Strict 时,文档写入会失败
  • 对已有字段,一旦已经有数据写入,就不再支持修改字段定义

    • 因为 Lucene 实现的倒排索引,一旦生成后,就不允许修改
  • 如果希望改变字段类型,必须调用 Reindex API,重建索引

  • 原因

    • 如果修改了字段的数据类型,会导致已经被索引的数据无法被搜索
    • 但是如果是增加新的字段,就不会有这样的影响

直接写入测试数据

POST sites_v1/_doc
{
  "id":"mock id",
  "keywords":["search"],
  "host":"baidu.com"
}

响应如下

{
  "_index" : "sites_v1",
  "_id" : "g-q4nYABjf0SD-BWAH69",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

未指定 Mapping 写入数据的时候,Elasticsearch 会根据写入的文档来自动生成 Mapping

查看一下生成的 Mapping

# 查看自动生成的 Mapping
GET sites_v1/_mapping
# 结果如下
{
  "sites_v1" : {
    "mappings" : {
      "properties" : {
        "host" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "id" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "keywords" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

假设自动生成的 Mapping 有的字段类型识别错了,那就在这个基础上手动修改,不用每个字段都去写了。

假设 这个自动生成的 Mapping 不是很满意,那就手动改一下

# 删除 Index
DELETE sites_v1

# 修改后指定 Mapping
PUT sites_v1
{
  "mappings": {
    "properties": {
      "host": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "id": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "keywords": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

2. Settings

一般创建索引时需要在Settings中手动指定主分片与副本分片数。

 "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 1
    }

删除索引后重新创建,可以和Mapping一起设置。

# 删除索引后重新创建
DELETE sites_v1
PUT sites_v1
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "host": {
        "type": "keyword"
      },
      "id": {
        "type": "keyword"
      },
      "keywords": {
        "type": "text"
      }
    }
  }
}

对于生产环境中分片的设定,需要提前做好容量规划

  • 分片数设置过小
    • 导致后续无法增加节点实现水平扩展
    • 当个分片的数据量太大,导致数据重新分配耗时
  • 分片数设置过大,(7.0 开始默认主分片设置成1 ,解决了 over-sharding 的问题)
    • 影响搜索结果的相关性打分,影响统计结果的准确性
    • 单个节点上过多的分片,会导致资源浪费,同时也会影响性能

3. 分词器

需要单独安装。

# 需要先 close Index
POST sites_v1/_close
# 为 Index 单独指定分词器
PUT sites_v1/_settings
{
  "index":{
    "analysis.analyzer.default.type":"ik_max_word",
    "analysis.search_analyzer.default.type":"ik_smart"
  }
}
# 然后继续开启
POST sites_v1/_open

关闭的索引被阻止进行读/写操作,并且不允许打开的索引允许的所有操作。无法索引文档或在封闭索引中搜索文档。这允许封闭索引不必维护用于索引或搜索文档的内部数据结构,从而减少集群的开销。

4. 写入数据

使用批量操作_bulk写入部分数据

3. 其他

1. 索引别名

建议为所有的 Index 都指定一个别名,后续可以进行索引的平滑切换。

比如创建的 Index 名为sites_v1,通过如下请求添加了一个别名sites

# alias 指定别名 
POST _aliases
{
  "actions": [
    {
      "add": {
        "alias": "sites",
        "index": "sites_v1"
      }
    }
  ]
}

后续就能通过sites来访问索引sites_v1了。

由于 Mapping 设置之后就不能改了,所以假如某天需要调整 Mapping 就只能创建一个新的 Index。

比如叫做sites_v2,然后只需要把sites_v2别名设置为sites就能直接不做任何改动的情况下平滑过渡到新 Index。

# alias 指定别名到新 Index 同时移除旧的 
POST _aliases
{
    "actions": [
        { "add": {
            "alias": "sites",
            "index": "sites_v2"
        },
        "remove": {
            "alias": "sites",
            "index": "sites_v1"
        }}
    ]
}

显式映射

您可以使用create index API 创建具有显式映射的新索引。

PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  }, 
      "name":   { "type": "text"  }     
    }
  }
}

将字段添加到现有映射

可以使用更新映射API 将一个或多个新字段添加到现有索引。

以下示例添加employee-idindex映射参数值为 false keyword字段。 。这意味着该字段的值已存储但未编入索引或可用于搜索。indexfalse``employee-id

PUT /my-index-000001/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}

更新字段的映射

除支持的映射参数外,您不能更改现有字段的映射或字段类型。更改现有字段可能会使已编入索引的数据无效。

如果您需要更改其他索引中某个字段的映射,请创建一个具有正确映射的新索引,并将数据重新索引到该索引中。

查看特定字段的映射

如果您只想查看一个或多个特定字段的映射,您可以使用获取字段映射API。

如果您不需要索引的完整映射或者您的索引包含大量字段,这将很有用。

以下请求检索该employee-id字段的映射。

GET /my-index-000001/_mapping/field/employee-id