// //
//

ES 文档与索引介绍

在之前的文章中,介绍了 ES 整体的架构和内容,这篇主要针对 ES 最小的存储单位 - 文档以及由文档组成的索引进行详细介绍。

会涉及到如下的内容:

  1. 文档的 CURD 操作。
  2. Dynamic Mapping 和显示 Mapping 的区别
  3. 常见 Mapping 类型与常见参数介绍
  4. Index Template 和 Dynamic Template

对文档进行操作#

单个文档 CRUD#

和常见的数据库类似,ES 也支持 CURD 操作:

下面展示了对单个 ES 文档的操作:

操作名称 URL 解释
Index image-20220406215957677 创建或者更新索引中的文档。在指定 id 的情况下,如果 id 存在,则会更新。如果不指定,则会创建。
Get image-20220406220223805 查询某个文档。
Delete DELETE //_doc/<_id> 删除某个指定的文档。
Update POST //_update/<_id> 更新某个文档中的内容,可以理解成 Patch 的更新。如果想完全替换文档,请使用 index.

下面是实际操作文档的例子, 打开 kibana 的开发者工具:

先来创建一个文档:

ES 在创建文档时,会有两种方式 index 和 create。index 与 create 不同在于,在指定 id 的情况下,如果 id 存在,index 会覆盖,同时版本号+1,而 create 会报错不让创建。

这里手动指定 id 为10,使用 index 方法,创建了一个文档,注意版本号为 1。

image-20220406222248162

注意再次发送同样的情况,可以看到正常执行,版本号变成 2了。

image-20220406222310526

但是使用 create 方法:

image-20220406222351472

这里报错,显示文档已经存在。

需要注意的 ES 这里的更新并不是正常理解的更新,而是先把老文档删掉,然后创建一个新文档出来。

接着对文档进行更新:

image-20220407073426264

可以看到这里只更新 user 字段,这种更新和之前 index 那种更新不同,属于部分更新,将增加的内容 merge 进原始文档。

对文档进行读取,这里由于之前更新了三次,所以 version = 3:

image-20220407073714504

删除文档就很好理解了,但有一点需要注意,删除文档时并不会立马释放空间,而是将文档标记位 deleted 状态,后台进程会在合适的时候清理这些标记位已经删除的文档。

批量文档操作#

批量写入

相较于当个文档的操作,大批量的操作对于 ES 来说,是更为常见的场景。ES 也提供了批量 API,该 API 支持在一次 API请求中包含 4 种类型, 并且 Response 中会针对每一条操作返回一个对应的结果。

POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

批量读取

可以同时传入多个文档 id,进行读取,多个文档可以属于不同的索引。

GET /_mget
{
  "docs": [
    {
      "_index": "my-index-000001",
      "_id": "1"
    },
    {
      "_index": "my-index-000001",
      "_id": "2"
    }
  ]
}

索引 - Mapping#

索引是多个文档的集合,体现了逻辑空间的概念。对于每个索引来说都可以设置 Mapping 和 Setting 两部分。

其中 Mapping 定义了文档包含字段的类型与名称,以及如倒排索引,分词的一些设置。Setting 定义了如何将数据分布保存在不同的节点上。

数据类型#

ES 中的数据类型分为三种:

  • 简单类型
  • 复杂类型
    • 对象类型
    • 嵌套类型
  • 特殊类型
    • 地理位置等

下图中显示了 ES 中常见的简单数据类型以及和 SQL 对应的关系。

Elasticsearch type Elasticsearch SQL type SQL type SQL precision
Core types
null null NULL 0
boolean boolean BOOLEAN 1
byte byte TINYINT 3
short short SMALLINT 5
integer integer INTEGER 10
long long BIGINT 19
double double DOUBLE 15
float float REAL 7
half_float half_float FLOAT 3
scaled_float scaled_float DOUBLE 15
keyword type family keyword VARCHAR 32,766
text text VARCHAR 2,147,483,647
binary binary VARBINARY 2,147,483,647
date datetime TIMESTAMP 29
ip ip VARCHAR 39

Dynamic Mapping#

我们知道,Mapping 类似于数据库 Scheme 的定义,但回想之前对文档 CURD 的操作时,我们并未手动设置 Mapping,但可以自动创建文档,原因就在于利用了 Dynamic Mapping 的特性。就是即使索引不存在时,也可以手动创建索引,并根据文档信息自动推算出对应的 Mapping 关系。

比如之前创建的文档,如下就是生成的 Mapping 关系,ES 自动将 company 和 user 推断为 text 字段。

image-20220407085317352

当 Dynamic Mapping 也有自己的缺点:就是推算不准确,比如上面的例子,company 和 user 的字段为 keyword 类型更为合适,以至于搜索时出现一些问题。

dynamic Mapping 可以通过 dynamic 字段进行控制, 其值为 true,false,strict 三种类型。

对于已经创建的索引,在修改 Mapping 分为两种情况:

  • 增加新的字段:
    • dynamic 为 true,新字段写入后,Mapping 也会被更新
    • dynamic 为 false,字段可以写入到 _source, 但 Mapping 不会被更新,自然也不会被索引
    • dynamic 为 strict,不允许写入
  • 修改已经存在字段的类型:
    • 不允许修改,因为 Lucene 生成的倒排索引,不允许被修改。
    • 除非重新生成索引。

显示指定 Mapping#

与 Dynamic Mapping 不同,显示指定 Mapping 可以允许我们手动指定 Mapping 结构。

编写 Mapping 有两种方式:

  • 可以参考 doc
  • 利用 dynamic 自动创建功能,查询后,自己再编辑成想要的结构。

看一个简单的例子:

PUT user
 {
  "user" : {
    "mappings" : {
      "properties" : {
        "company" : {
          "type" : "keyword"
          "null_value": "NULL"
          }
        },
        "name" : {
          "type" : "keyword""index_options": "offsets"
        },
        "id_card" : {
          "type" : "keyword",
          "index": false # 表示该字段不需要被索引,不用被搜索到
        }
      }
  }
}

"null_value":表示对 NULL 值可以进行搜索。

"index": false 表示该字段不需要被索引,不用被搜索到

"index_options": "offsets" 表示对倒排索引的结构进行设置:

  • docs :表示记录 doc id
  • freqs :表示记录 doc id 和 term frequencies
  • position :表示记录 doc id 和 term frequencies 和 term position(Text 类型默认记录为 position)
  • offsets: 表示记录 doc id 和 term frequencies 和 term position 以及 character offset.

关于倒排可以查看之前写的这篇文章

Index Template 和 Dynamic Template#

Index Template#

考虑到数据不断增长的情况的,就需要按照一定的规则,将数据分散在不同的 Index 中。但每次都需要为每个 Index 设置 Mapping 和 Setting 关系。

这时 Index Template 就可以很好满足这个需求。

在 Index Template 中,可以通过设置一个通配名称,当创建的索引的名称,满足该条件时,就会使用模板的规则。

Note:

  • 模板只会在创建新索引时生效,修改模板不会影响已经创建的索引。
  • 可以设置多个模板,通过 "order" 参数,控制那个模板的规则生效。

下面这个例子就是为告警建立的一个 template,当创建的名字以 alarm 开头时,就会使用该索引。

image-20220415092031928

Dynamic Template#

在上面 Dynamic Mapping 的介绍中知道,ES 对于没有设置 Mapping 字段的内容,会自己推算一个类型,但这就可能造成推算类型不准确的情况。

这时就可以用 Dynamic Template 来解决,通过规范插入的字段的名称,来指定他的类型:

  • 比如可以 is 开头的字段,都设置成 boolean
  • long_ 开头的字段,设置成 long
  • 所有字符串类型,设置成 keyword

Dynamic Template 直接作用在索引上, 看下面这个例子。

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "long_num": "5", 
  "long_text": "foo" 
}

当匹配到以 long 开头的字符串时并且不包含以 _text 结尾,会将其设置成 long 类。

总结#

本篇文章中,主要是对 ES 文档和索引的设置进行了说明。

ES 文档支持 CURD 操作,但需要知道 Index 和 create 的区别在于,对于指定 id 情况下的处理方式不同。同时为了适应大数据量的读取和写入,可以用 bulk api.

对于 ES 索引来说,在创建时,支持两种方式来指定 Setting 和 Mapping 的关系。一种 Dynamic Mapping,这种方式不需要手动设置 Index 格式,会根据文档自动的创建,但缺点在于推断的类型不不准确。而显示 Mapping,可以手动规定 index 的格式。

考虑到数据不断增长的情况,需要将数据拆分到不同的 index 上,可以通过 IndexTemplate 实现。

对于 Dynamic Mapping,推断不准确的情况,可以通过 Dynamic Template 手动规定创建的类型。

参考#

https://www.elastic.co/guide/en/elasticsearch/reference/7.16/docs.html

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/mapping-params.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html

posted @   来份锅包肉  阅读(1549)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示
主题色彩