[译] Elasticsearch 新手指南

Elasticsearch 新手指南

图片来自 Markus Spiske on Unsplash

Elasticsearch 是一种支持非结构化数据的复杂聚合的分布式、可扩展的分析类搜索引擎。html

**相似于 NoSQL 数据库,Elasticsearch 是为处理非架构化数据格式并动态肯定字段数据类型而建立的。它处理的主要数据格式是 JSON(Javascript Object Notation)**文档。JSON schema-less 的数据格式使得数据存储变得很灵活,而且易于添加数据而无需管理或者建立数据关系。前端

然而,Elasticsearch 并不必定能做为 NoSQL 数据库使用。**Elasticsearch 与 NoSQL 是有差异的,并且它自身也有一些局限性。**例如,Elasticsearch 分布式系统在执行事务的时候会增长一层复杂性。尽管完成分布式事务也不是不可能,但为了简化流程仍是尽量避免使用它的分布式事务处理。node

Elasticsearch 还会认为提供给节点的内存是足够的。所以它不擅长处理内存溢出。这就使得 Elasticsearch 相比于其余的数据存储系统鲁棒性更低。android

Elasticsearch 常被用来做为其余类型数据库的辅助工具。记住 Elasticsearch 是为速度而生的这一点很重要。它是搜索和过滤文档的理想之选。ios

节点和集群

Elasticsearch 由多个节点构成(也叫作 Elasticsearch 实例),**一组链接在一块儿的节点则被称为集群。同一个集群内的全部节点都知道集群内的其余节点的信息。集群内的每一个节点均可以经过 HTTP 请求(POST, GET, PUT, DELETE)**来执行增删改查操做。这种模式使得节点能够将客户请求转交其余节点来完成。git

1 个包含 3 个节点 (ES 实例) 和 5 个分片的集群

索引和分片

Elasticsearch 的索引有时候会被误认为跟关系型数据库中的索引是同样的。可是,理解它们之间的区别相当重要。**Elasticsearch 索引是一组分片的集合,而文档则均匀分布在这些分片上的。**若是没有特别说明,Elasticsearch 默认为每一个索引分配 5 个主分片。上图可见这种分配模式。github

例如,你可能会定义一个名为 products 的索引。这个索引里存在不一样的产品文档,以下所示:docker

[{
 "title": "Apple MacBook Pro 13-Inch 'Core i7' 2.4",
 "price": "$2559",
 "sku": "123SampleBLK20",
 "itemCondition": "New",
 "availability": "IN_STOCK",
},
{
 "title": "Apple iPad Pro 12.9 (Wi-Fi Only - 4th Gen) 128GB",
 "price": "$699",
 "sku": "123SampleBLK21",
 "itemCondition": "Used",
 "availability": "IN_STOCK",
},
{
 "title": "Samsung Galaxy S20 - 128GB",
 "price": "$1199",
 "sku": "123SampleBLK22",
 "itemCondition": "New",
 "availability": "OUT_OF_STOCK",
}]
复制代码

当文档被添加到一个索引时,Elasticsearch 会决定哪一个分片用来装载这些文档。**分片是均匀分布在集群内的节点上的。**若是新的节点加入到集群中,Elasticsearch 将在集群里从新均匀地分配分片。数据库

注意一个额外的节点被添加到了集群,如今这些分片被从新均匀分布了。

Elasticsearch 的“活跃”分片也值得提一下。活跃分片正如它的名字所表达的,指的是活跃着的保存有数据的分片。 若是文档不够多,不足以充分使用全部的分片,那么其中一些分片尽管是分配给这个索引的,也不会被认为是活跃的。稍后你将看到一个例子。后端

副本

副本是分片的一种类型,只不过它是用来提升搜索性能并做为主分片的备份的。**一个完整的副本由 5 个副本分片组成。**所以咱们一般能够认为每一个索引拥有一个副本。

副本分片能够做为可靠的故障转移,由于它们不会跟它所复制的数据被分配到同一个节点。若是你熟悉 RAID**(冗余独立磁盘阵列)**,那副本分片跟它有些相似。数据被镜像拷贝到一个冗余的磁盘,在 Elasticsearch 里其实就是镜像拷贝到一个分片。而且因为分片在一个独立的节点上,若是含有主分片的节点故障了,副本仍然是可用的。而副本分片的节点和主分片的节点同时故障的风险相对较小。

阐明与“关系型数据库”的类比

Elasticsearch 理解起来可能会有点复杂。这些困惑主要是 Elasticsearch 团队在描述这些概念时所使用的一些不许确的类比形成的。在那之后,Elasticsearch 团队也试图解释这些误解。

大多数互联网上的资料都把一个索引和一个单独的关系型数据库作比较。那如今你可能会想,与其说索引像一个数据库,它难道不更像一张表吗?

你的理解是正确的,索引确实跟一张表相似。然而,在 Elasticsearch v.6 以及以前的版本中,一直有 类型 映射的概念。类型是用来表示一个索引内文档的类别的。举个例子,若是 “twitter” 是一个索引,那么咱们能够描述 “twitter” 文档里的两种类型:“tweet” 和 “user”。 类型这个概念存在太多问题,所以我不会在这篇文章中深刻探讨,但本质上,Elasticsearch 的类型是模仿了关系型数据库表。

我我的建议不要把 Elasticsearch 跟关系型数据库关联起来。这样只会让你更困惑,其实我也一样所以感到困惑。

安装和入门

如前文所述,与 Elasticsearch 交互的主要方式是经过 HTTP 请求(RESTFUL APIs)。 在本节内容里,做为入门,咱们会回顾一些在 Elasticsearch 实例中建立索引的基本方法。

开始使用 Elasticsearch 以前,须要安装 Docker 并建立一个名为 data/elasticsearch 的文件夹。而后运行下面的 docker 命令下载 Elasticsearch 的 docker 镜像文件并启动 docker 容器。

docker run --restart=always -d --name elasticsearch \\
    -e "discovery.type=single-node"  \\
    -v ~/data/elasticsearch:/usr/share/elasticsearch/data \\
    -p 9200:9200 \\
    -p 9300:9300 \\
    docker.elastic.co/elasticsearch/elasticsearch:7.9.2
复制代码

如今你就能够经过 [http://localhost:9200](http://localhost:9200) 访问 Elasticsearch 全部的 API 了。

建立一个新索引

你能够用下面两种方法中的任意一种来建立文档,经过 PUT 请求或者 POST 请求。由于我要使用的是 Elasticsearch v.7 版本,因此我会避免提到与类型有关的话题。我会坚持使用 Elasticsearch 的默认类型 _doc 来操做索引和文档。

咱们能够用以下方式建立一个空索引:

PUT http://localhost:9200/products
复制代码

咱们也能够经过在咱们想要的索引中插入一个文档的方式来建立索引,以下所示:

POST: http://localhost:9200/product/_doc/

{
 "title": "Apple MacBook Pro 13-Inch 'Core i7' 2.4",
 "price": "$2559",
 "sku": "123SampleBLK20",
 "itemCondition": "New",
 "availability": "IN_STOCK",
}
复制代码

上面的请求将产生以下响应报文:

{

  "_index": "product",
  "_type": "_doc",
  "_id": "xUs3MHYBPq6LuxBgrCHN",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
},
  "_seq_no": 6,
  "_primary_term": 1
}
复制代码

在上面的响应报文里,每一个插入的文档都有一个随机生成的识别码 _id。可是若是你想指定识别码,就须要把 POST 请求改成一个 PUT 请求,并以下所示在请求的末尾添加一个识别码:

PUT: http://localhost:9200/product/_doc/1
复制代码

再次回到上面的响应报文,咱们注意到一共有 2 个分片,而其中一个分片在结果中显示是成功的。我在前文有简要的说起,活跃分片装载了数据,而副本分片装载了一份数据的拷贝。所以,这段响应报文告诉咱们数据是从 2 个活跃分片**(其中一个是副本分片)**中的一个获取的。

咱们能够经过调用 CAT (压缩并对齐文本) API 来验证分片数量,以下所示:

GET http://localhost:9200/_cat/shards/product
复制代码

CAT API 是用来对 Elasticsearch 集群进行统计查询的。咱们能够查询关于节点、集群、索引、模板以及其它的 Elasticsearch 特征。

上面的请求会产生以下结果:

product 0 p STARTED    4 7kb 1xx.xx.x.x a6ffefa157e8
product 0 r UNASSIGNED
复制代码

这段响应报文告诉咱们在索引 product 里找到的分片**(在此它们都被标记为 0)**要么是副本 r,要么是主分片 p,而且状态是 STARTED 或者 UNASSIGNED。这段响应也告诉了咱们分片里的文档数量、磁盘大小、IP 地址和节点 id。

要获得 CAT API 请求的完整列表,咱们须要作以下请求:

GET http://localhost:9200/_cat/
复制代码

我推荐把这个请求保存到你易于访问的地方。由于这个 API 能够方便你学习 Elasticsearch。

搜索索引

Elasticsearch 强大的搜索功能是很难用几个段落就总结完的。我这里会提供 2 个基本的搜索功能以便大家入门:获取索引里的全部文档和经过识别码获取一个文档。我会在其余的文章里讨论更复杂、更有趣的搜索查询。

咱们能够用下面的请求获取一个索引里的所有文档:

GET http://localhost:9200/product/_search
复制代码

然而,在默认状况下,Elasticsearch 每次只会返回 45 个文档。不过咱们能够在查询字符串中提升这个限制值,正以下面请求里的 size 字段:

GET http://localhost:9200/product/_search?size=100
复制代码

经过识别码获取单一文档跟上文提到的添加一个文档的请求方法很相似,只不过要将 POST 请求改为 GET 请求,以下所示:

GET http://localhost:9200/product_entity/_doc/1
复制代码

结语

Elasticsearch 是一个强大的分析类搜索引擎。可是它操做起来会很复杂。

我在本文介绍了一些帮助大家入门的基础概念。但我仍是强烈推荐大家浏览 Elasticsearch v.7.9 或更高版本的文档 以及 Elasticsearch 博客 来加深和拓展你的理解。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索