ElasticSearch 的概念解析与使用方式(二)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: ElasticSearch 的概念解析与使用方式(二)


楔子



上一篇文章(可以点击传送门进行阅读)我们介绍了 ES 的基本概念以及安装方式,那么本次就来看看如何操作 ES。ES 支持客户端通过标准的 HTTP 请求来访问数据,并且 API 遵循 Restful 风格。


操作索引



我们说过,ES 的索引就类似于 MySQL 的数据库,因此我们首先要创建索引。

创建索引

方式:通过 PUT /{index} 即可创建指定名称的索引,举个例子。

PUT http://82.157.146.194:9200/people

此时我们便创建了一个索引叫 people,同时服务器会返回如下内容。

{
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "people"
}

返回的 JSON 包含三个字段,含义如下。

  • acknowledged:响应结果,true 表示添加成功;
  • shards_acknowledged:分片结果,true 表示分片成功;
  • index:创建的索引名称;


注意:索引的分片数量默认为 1,在 7.x 之前默认为 5。

如果添加的索引已存在,那么会返回错误信息,比如我们将索引 people 再创建一次。

f2db79758262c74036f8c6f0712dcd10.png

服务器依旧会返回一个 JSON,里面包含了详细的错误信息,这些信息都见名知意。并且不管什么错误,返回的错误信息的格式是固定的。

当然,如果你不确定添加的索引是否存在,那么在添加之前可以查看一下。

查看索引

方式:通过 GET /{index} 即可查看指定的索引信息。

GET http://82.157.146.194:9200/people

服务器返回内容如下。

56c138a2651446e970b76fc2b80c6b0c.png

里面有几个关键字段需要解释一下。

  • number_of_shards:分片数量,我们说 ES 会将 Index 切分成多份,每一份叫做一个 shard,从 7.x 开始默认只有一个 shard;
  • number_of_replicas:副本数量,每个 shard 可以配置多个副本,保证高可用,默认副本数为 1;
  • creation_date:索引的创建时间;
  • uuid:索引的唯一标识;

shard 也被称为主分片,primary shard

replica 也被称为副本分片,replica shard

不过我个人还是习惯称它们为分片和副本

以上就是查看索引,但如果索引不存在,会返回什么呢?比如我们查看 people2,这个索引是不存在的。

{
    "error": {
        "root_cause": [
            {
                "type": "index_not_found_exception",
                "reason": "no such index [people2]",
                "resource.type": "index_or_alias",
                "resource.id": "people2",
                "index_uuid": "_na_",
                "index": "people2"
            }
        ],
        "type": "index_not_found_exception",
        "reason": "no such index [people2]",
        "resource.type": "index_or_alias",
        "resource.id": "people2",
        "index_uuid": "_na_",
        "index": "people2"
    },
    "status": 404
}

返回的依旧是包含错误信息的 JSON,里面的字段解释了错误的原因。

查看全部索引

然后除了查询单个索引之外,也可以查询全部的索引。

GET http://82.157.146.194:9200/_cat/indices

里面的 _cat 表示查看,indices 表示索引,整体含义就是查看当前 ES 服务器的所有索引。

服务器会以一个二维表的形式返回,第一行是字段,剩余行是索引记录。其中字段的含义如下:

  • health:当前服务器健康状态,green 表示集群完整,yellow 表示单点正常、集群不完整,red 表示单点不正常;
  • status:索引的状态,是打开还是关闭;
  • index:索引的名称;
  • uuid:索引的唯一编号;
  • pri:分片(shard)的数量;
  • rep:副本(replica)的数量;
  • docs.count:可用文档(Document)的数量;
  • docs.deleted:文档删除状态(逻辑删除);
  • store.size:分片和副本整体占用的空间大小;
  • pri.store.size:分片占用的空间大小;
  • dataset.size:主分片占用的空间大小;

删除索引

说完了添加索引和查询索引,再来看看如何删除索引。相信删除的过程不用我说你也知道,发一个 DELETE 请求即可。

DELETE http://82.157.146.194:9200/people

服务器返回内容如下:

{
    "acknowledged": true
}

返回的 JSON 里面只包含一个 acknowledged 字段,为 true 表示删除成功。如果删除一个不存在的索引,那么会报错,比如这里再次删除索引 people。

{
    "error": {
        "root_cause": [
            {
                "type": "index_not_found_exception",
                "reason": "no such index [people]",
                "resource.type": "index_or_alias",
                "resource.id": "people",
                "index_uuid": "_na_",
                "index": "people"
            }
        ],
        "type": "index_not_found_exception",
        "reason": "no such index [people]",
        "resource.type": "index_or_alias",
        "resource.id": "people",
        "index_uuid": "_na_",
        "index": "people"
    },
    "status": 404
}

因此基于返回值我们很容易判断出,操作是否出现错误,以及错误原因是什么。

关于索引操作,再总结一下。

c5c28d01f5e6fa3e7f1733d1c09fc9f5.png

以上就是索引相关的操作,还是比较简单的。


文档操作


索引已经创建好了(刚才删除的 people 索引又重新创建了),接下来我们来创建文档,并添加数据。这里的文档可以类比关系型数据库中的表数据,添加的数据格式为 JSON。

另外我们知道在关系型数据库中,必须先定义好表、指定好字段才可以使用,但在 ES 中则不需要。因为 ES 对字段的处理是非常灵活的,我们可以忽略某个字段,或者新增一个字段。

新增文档

首先是添加一个新文档。

// 通过 PUT /{index}/_doc/{document_id} 添加文档
// 文档数据是一个 JSON
PUT http://123.57.183.166:9200/people/_doc/satori
{
    "name": "古明地觉",
    "age": 17,
    "gender": "female",
    "address": "地灵殿"
}

一个 document 就是一条 JSON 数据,每个 document 都有一个唯一的 id,其中 id 可以通过路径参数指定。返回响应如下:

{
    "_index": "people",
    "_id": "satori",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}

解释一下里面的字段:

  • _index:标识文档位于哪个索引中;
  • _id:每个文档都有一个唯一 id;
  • _version:版本号,当对文档执行增删改操作时,该文档的版本号会自增 1;
  • result:这里的 created 表示创建成功;
  • _shards.total:分片的总数;
  • _shards.successful:创建成功的分片数;
  • _shards.failed:创建失败的分片数;

到这里应该有人发现了,如果文档 id 每次都需要手动指定,未免有点麻烦。因此 ES 也可以帮我们生成文档 id,做法如下:

POST http://123.57.183.166:9200/girls/_doc
{
    "name": "芙兰朵露",
    "age": 400,
    "gender": "female",
    "address": "红魔馆"
}

这里我们没有指定文档 id,那么 ES 会自动生成,返回响应如下。

{
    "_index": "people",
    "_id": "HSW404wBlTaHOP7A6wd2",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}

注意这里的请求,如果通过路径参数手动指定了文档 id,那么 POST 和 PUT 请求均可。但如果没有指定文档 id,那么只能使用 POST 请求。

获取文档

目前我们已经在 people 这个 index 下面创建了两个 document,它们的 id 分别是 satori 和 HSW404wBlTaHOP7A6wd2,那么便可通过如下方式进行查询。

  • GET /people/_doc/satori
  • GET /people/_doc/HSW404wBlTaHOP7A6wd2

响应内容如下:

{
    "_index": "people",
    "_id": "satori",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "古明地觉",
        "age": 17,
        "gender": "female",
        "address": "地灵殿"
    }
}
{
    "_index": "people",
    "_id": "HSW404wBlTaHOP7A6wd2",
    "_version": 1,
    "_seq_no": 1,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "芙兰朵露",
        "age": 400,
        "gender": "female",
        "address": "红魔馆"
    }
}

里面的 _source 字段的值,就是我们添加的文档数据。

修改文档

说完了添加和查询,再来看看修改,比如我想将文档 id 为 'satori' 的文档中的 name 字段的值,改为 '古明地恋',要怎么做呢?

// 手动指定了文档 id,那么 POST 和 PUT 均可
// 如果没有指定,那么只能使用 POST
// 因此这里 POST 和 PUT 均可
POST /people/_doc/satori
{
    "name": "古明地恋",
    "age": 17,
    "gender": "female",
    "address": "地灵殿"
}

非常简单,直接改即可。就像新建文档一样,输入相同的 URL,会将旧的文档数据替换掉,并且版本号会自增 1。ES 服务器返回数据如下:

{
    "_index": "people",
    "_id": "satori",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 2,
    "_primary_term": 1
}

我们看到 _version 从初始的 1 变成了 2,并且此时的 result 不再是 created,而是 updated,表示更新。并且在更新的过程中,字段数量可以和之前不一样,也就是说我们可以新增字段、删除字段,非常灵活。

并且由于指定了文档 id,所以 POST 请求和 PUT 均可。这里我们将另一个文档也给改了,并调整一下字段。

PUT /people/_doc/HSW404wBlTaHOP7A6wd2
{
    "name": "芙兰朵露·斯卡雷特",
    "年龄": 400,
    "gender": "female",
    "address": "东方红魔馆"
}

ES 服务器返回数据如下:

{
    "_index": "people",
    "_id": "HSW404wBlTaHOP7A6wd2",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 3,
    "_primary_term": 1
}

注意:修改数据必须要指定文档 id,如果不指定的话,那么会生成一个不重复的新的文档 id,此时就是新增文档。如果想修改文档,那么必须手动指定它的 id,从而实现替换。

然后再看一下里面的 _seq_no 字段,你可以认为 ES 内部有一个全局的计数器,只要有文档发生增删改,这个计数器就会自增 1,而 _seq_no 保存了当前时刻的全局计数器的值。

我们查看一下这两个文档数据。

{
    "_index": "people",
    "_id": "satori",
    "_version": 2,
    "_seq_no": 2,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "古明地恋",
        "age": 17,
        "gender": "female",
        "address": "地灵殿"
    }
}
{
    "_index": "people",
    "_id": "HSW404wBlTaHOP7A6wd2",
    "_version": 2,
    "_seq_no": 3,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "芙兰朵露·斯卡雷特",
        "年龄": 400,
        "gender": "female",
        "address": "东方红魔馆"
    }
}

数据发生了变化,并且此时字段可以自由调整。如果是关系型数据库,那么数据必须和表的已有字段相匹配,我们不能给一个不存在的字段添加数据。如果真想这么做,那么必须先通过 DDL 修改表字段。

所以在 ES 中,Type 的概念已经不存在了,因为它和全局索引的设计理念是冲突的,不过 Index、Document、Field 还是可以和关系型数据库的 Database、Row、Column 对应的。

删除文档

说完了,查询、添加、修改,最后来看看删除,删除很简单,直接通过 DELETE 请求即可。

DELETE /people/_doc/satori

服务器返回数据如下。

{
    "_index": "people",
    "_id": "satori",
    "_version": 3,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 4,
    "_primary_term": 1
}

因为涉及到增删改,所以当前文档的 _version 自增 1,并且 result 为 deleted,表示删除。如果要删除的文档不存在,那么 result 字段的值就是 not_found。

注意:文档被删除后,不会立即从磁盘上移除,只是被标记成已删除(逻辑删除)。如果我们查询一个已被删除(或者不存在)的文档,会返回如下信息:

{
    "_index": "people",
    "_id": "satori",
    "found": false
}

所以在获取文档时,可以先通过 found 字段判断是否存在,如果存在,再通过 _source 字段拿到具体的文档记录。

我们总结一下,文档操作的 API。

85e00451fab7c5e0a641f179353fcdf5.png

添加文档时,如果在路径参数中没有指定文档 id,即 /index/_doc,那么必须用 POST 请求,此时 ES 会自动为新增的文档生成一个不重复的 id。

如果添加文档时,在路径参数中指定了文档 id,即 /index/_doc/document_id,那么可以用 PUT 也可以用 POST,并且当指定的文档 id 已存在时,还能实现修改的效果。所以文档的新增和修改实际上用的是同一套接口,至于到底是新增还是修改,就看返回的响应中 result 字段的值是 "created" 还是 "updated"。

查询文档时,API 为 GET /index/_doc/document_id,然后通过返回响应中的 found 字段,可以判断文档是否存在。如果是 true,那么代表该文档存在,否则不存在。

最后是删除,API 为 DELETE /index/_doc/document_id,如果要删除的文档存在,那么返回响应中的 result 字段为 "deleted",否则为 "not_found"。事实上在大部分情况下,我们并不关心删除的文档是否存在,直接删就完事了,反正文档不存在时啥事也没有。正如添加文档时,很多时候我们也不关心文档是否存在,如果存在,那么替换掉就完事了。


小结



本篇文章便简单介绍了索引以及文档的操作,当然目前都很简单,因为始终都是基于文档 id 操作单条文档。而 ES 基于 JSON 自定义了一套规则,按照这些规则,我们可以对文档进行批量操作,实现复杂的查询。

关于如何对文档进行批量查询,我们下一篇文章再说。

本文由耳濡目染同志独家赞助。

相关文章
|
2月前
|
存储 分布式计算 大数据
大数据-169 Elasticsearch 索引使用 与 架构概念 增删改查
大数据-169 Elasticsearch 索引使用 与 架构概念 增删改查
62 3
|
2月前
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
83 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
1月前
|
测试技术 API 开发工具
ElasticSearch核心概念:倒排索引
ElasticSearch核心概念:倒排索引
52 6
|
28天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
40 1
|
1月前
|
消息中间件 存储 负载均衡
Apache Kafka核心概念解析:生产者、消费者与Broker
【10月更文挑战第24天】在数字化转型的大潮中,数据的实时处理能力成为了企业竞争力的重要组成部分。Apache Kafka 作为一款高性能的消息队列系统,在这一领域占据了重要地位。通过使用 Kafka,企业可以构建出高效的数据管道,实现数据的快速传输和处理。今天,我将从个人的角度出发,深入解析 Kafka 的三大核心组件——生产者、消费者与 Broker,希望能够帮助大家建立起对 Kafka 内部机制的基本理解。
61 2
|
2月前
|
存储 NoSQL MongoDB
MongoDB 概念解析
10月更文挑战第12天
24 0
MongoDB 概念解析
|
2月前
|
存储 缓存 监控
深入解析:Elasticsearch集群性能调优策略与最佳实践
【10月更文挑战第8天】Elasticsearch 是一个分布式的、基于 RESTful 风格的搜索和数据分析引擎,它能够快速地存储、搜索和分析大量数据。随着企业对实时数据处理需求的增长,Elasticsearch 被广泛应用于日志分析、全文搜索、安全信息和事件管理(SIEM)等领域。然而,为了确保 Elasticsearch 集群能够高效运行并满足业务需求,需要进行一系列的性能调优工作。
106 3
|
2月前
|
存储 安全 网络协议
Elasticsearch 配置文件解析
【10月更文挑战第3天】Elasticsearch 配置文件解析
87 3
|
2月前
|
供应链 网络协议 数据安全/隐私保护
|
2月前
|
前端开发 JavaScript Shell
深入解析前端构建利器:webpack核心概念与基本功能全览
深入解析前端构建利器:webpack核心概念与基本功能全览—
26 0