Elasticsearch权威指南-学习笔记1

阅读 87

2022-07-18


和 Elasticsearch 交互​​编辑​​

和 Elasticsearch 的交互方式取决于 你是否使用 Java

Java API​​编辑​​

如果你正在使用 Java,在代码中你可以使用 Elasticsearch 内置的两个客户端:

节点客户端(Node client)

节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点。

传输客户端(Transport client)

轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上。

两个 Java 客户端都是通过 9300 端口并使用 Elasticsearch 的原生 传输 协议和集群交互。集群中的节点通过端口 9300 彼此通信。如果这个端口没有打开,节点将无法形成一个集群。

 

Java 客户端作为节点必须和 Elasticsearch 有相同的 主要 版本;否则,它们之间将无法互相理解。

更多的 Java 客户端信息可以在 ​​Elasticsearch Clients​​ 中找到。

RESTful API with JSON over HTTP​​编辑​​

所有其他语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信,你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上,正如你所看到的,你甚至可以使用 ​​curl​​ 命令来和 Elasticsearch 交互。

 

Elasticsearch 为以下语言提供了官方客户端 --Groovy、JavaScript、.NET、 PHP、 Perl、 Python 和 Ruby—​还有很多社区提供的客户端和插件,所有这些都可以在 ​​Elasticsearch Clients​​ 中找到。

一个 Elasticsearch 请求和任何 HTTP 请求一样由若干相同的部件组成:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

被 ​​< >​​ 标记的部件:

​VERB​

适当的 HTTP 方法 或 谓词 : ​​GET​​​、 ​​POST​​​、 ​​PUT​​​、 ​​HEAD​​​ 或者 ​​DELETE​​。

​PROTOCOL​

​http​​​ 或者 ​​https​​​(如果你在 Elasticsearch 前面有一个 ​​https​​ 代理)

​HOST​

Elasticsearch 集群中任意节点的主机名,或者用 ​​localhost​​ 代表本地机器上的节点。

​PORT​

运行 Elasticsearch HTTP 服务的端口号,默认是 ​​9200​​ 。

​PATH​

API 的终端路径(例如 ​​_count​​​ 将返回集群中文档数量)。Path 可能包含多个组件,例如:​​_cluster/stats​​​ 和 ​​_nodes/stats/jvm​​ 。

​QUERY_STRING​

任意可选的查询字符串参数 (例如 ​​?pretty​​ 将格式化地输出 JSON 返回值,使其更容易阅读)

​BODY​

一个 JSON 格式的请求体 (如果请求需要的话)

例如,计算集群中文档的数量,我们可以用这个:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}
'

Elasticsearch 返回一个 HTTP 状态码(例如:​​200 OK​​​)和(除`HEAD`请求)一个 JSON 格式的返回值。前面的 ​​curl​​ 请求将返回一个像下面一样的 JSON 体:

{
"count" : 0,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
}
}

在返回结果中没有看到 HTTP 头信息是因为我们没有要求`curl`显示它们。想要看到头信息,需要结合 ​​-i​​​ 参数来使用 ​​curl​​ 命令:

curl -i -XGET 'localhost:9200/'

在书中剩余的部分,我们将用缩写格式来展示这些 ​​curl​​​ 示例,所谓的缩写格式就是省略请求中所有相同的部分,例如主机名、端口号以及 ​​curl​​ 命令本身。而不是像下面显示的那样用一个完整的请求:

curl -XGET 'localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}'

我们将用缩写格式显示:

GET /_count
{
"query": {
"match_all": {}
}
}

拷贝为 cURL​​在 Sense 中查看​​ 

事实上, ​​Sense 控制台​​ 也使用这样相同的格式。如果你正在阅读这本书的在线版本,可以通过点击 Sense 链接视图在 Sense 上打开和运行示例代码。

面向文档​​编辑​​

在应用程序中对象很少只是一个简单的键和值的列表。通常,它们拥有更复杂的数据结构,可能包括日期、地理信息、其他对象或者数组等。

也许有一天你想把这些对象存储在数据库中。使用关系型数据库的行和列存储,这相当于是把一个表现力丰富的对象塞到一个非常大的电子表格中:为了适应表结构,你必须设法将这个对象扁平化—通常一个字段对应一列—而且每次查询时又需要将其重新构造为对象。

Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档。Elasticsearch 不仅存储文档,而且 索引 每个文档的内容,使之可以被检索。在 Elasticsearch 中,我们对文档进行索引、检索、排序和过滤—而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。

JSON​​编辑​​

Elasticsearch 使用 JavaScript Object Notation(或者 ​​JSON​​)作为文档的序列化格式。JSON 序列化为大多数编程语言所支持,并且已经成为 NoSQL 领域的标准格式。 它简单、简洁、易于阅读。

下面这个 JSON 文档代表了一个 user 对象:

{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}

虽然原始的 ​​user​​ 对象很复杂,但这个对象的结构和含义在 JSON 版本中都得到了体现和保留。在 Elasticsearch 中将对象转化为 JSON 后构建索引要比在一个扁平的表结构中要简单的多。

 

几乎所有的语言都有可以将任意的数据结构或对象 转化成 JSON 格式的模块,只是细节各不相同。具体请查看 serialization 或者 marshalling 这两个处理 JSON 的模块。官方 ​​Elasticsearch 客户端​​ 自动为您提供 JSON 转化。

适应新环境​​编辑​​

为了让大家对 Elasticsearch 能实现什么及其上手难易程度有一个基本印象,让我们从一个简单的教程开始并介绍索引、搜索及聚合等基础概念。

我们将一并介绍一些新的技术术语,即使无法立即全部理解它们也无妨,因为在本书后续内容中,我们将继续深入介绍这里提到的所有概念。

接下来尽情享受 Elasticsearch 探索之旅。

创建一个雇员目录​​编辑​​

我们受雇于 Megacorp 公司,作为 HR 部门新的 “热爱无人机” ("We love our drones!")激励项目的一部分,我们的任务是为此创建一个员工目录。该目录应当能培养员工认同感及支持实时、高效、动态协作,因此有一些业务需求:

  • 支持包含多值标签、数值、以及全文本的数据
  • 检索任一员工的完整信息
  • 允许结构化搜索,比如查询 30 岁以上的员工
  • 允许简单的全文搜索以及较复杂的短语搜索
  • 支持在匹配文档内容中高亮显示搜索片段
  • 支持基于数据创建和管理分析仪表盘

索引员工文档​​编辑​​

第一个业务需求是存储员工数据。 这将会以 员工文档 的形式存储:一个文档代表一个员工。存储数据到 Elasticsearch 的行为叫做 索引 ,但在索引一个文档之前,需要确定将文档存储在哪里。

一个 Elasticsearch 集群可以 包含多个 索引 ,相应的每个索引可以包含多个 类型 。 这些不同的类型存储着多个 文档 ,每个文档又有 多个 属性 。

Index Versus Index Versus Index

你也许已经注意到 索引 这个词在 Elasticsearch 语境中有多种含义, 这里有必要做一些说明:

索引(名词):

如前所述,一个 索引 类似于传统关系数据库中的一个 数据库 ,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。

索引(动词):

索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询。这非常类似于 SQL 语句中的 ​​INSERT​​ 关键词,除了文档已存在时,新文档会替换旧文档情况之外。

倒排索引:

关系型数据库通过增加一个 索引 比如一个 B树(B-tree)索引 到指定的列上,以便提升数据检索速度。Elasticsearch 和 Lucene 使用了一个叫做 倒排索引 的结构来达到相同的目的。

+ 默认的,一个文档中的每一个属性都是 被索引 的(有一个倒排索引)和可搜索的。一个没有倒排索引的属性是不能被搜索到的。我们将在 ​​倒排索引​​ 讨论倒排索引的更多细节。

对于员工目录,我们将做如下操作:

  • 每个员工索引一个文档,文档包含该员工的所有信息。
  • 每个文档都将是​​employee​类型
  • 该类型位于索引​megacorp​​ 内。
  • 该索引保存在我们的 Elasticsearch 集群中。

实践中这非常简单(尽管看起来有很多步骤),我们可以通过一条命令完成所有这些动作:

PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}

注意,路径 ​​/megacorp/employee/1​​ 包含了三部分的信息:

​megacorp​

索引名称

​employee​

类型名称

​1​

特定雇员的ID

请求体 —— JSON 文档 —— 包含了这位员工的所有详细信息,他的名字叫 John Smith ,今年 25 岁,喜欢攀岩。

很简单!无需进行执行管理任务,如创建一个索引或指定每个属性的数据类型之类的,可以直接只索引一个文档。Elasticsearch 默认地完成其他一切,因此所有必需的管理任务都在后台使用默认设置完成。

进行下一步前,让我们增加更多的员工信息到目录中:

PUT /megacorp/employee/2
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}

PUT /megacorp/employee/3
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}

检索文档​​编辑​​

目前我们已经在 Elasticsearch 中存储了一些数据, 接下来就能专注于实现应用的业务需求了。第一个需求是可以检索到单个雇员的数据。

这在 Elasticsearch 中很简单。简单地执行 一个 HTTP ​​GET​​ 请求并指定文档的地址——索引库、类型和ID。 使用这三个信息可以返回原始的 JSON 文档:

GET /megacorp/employee/1

返回结果包含了文档的一些元数据,以及 ​​_source​​ 属性,内容是 John Smith 雇员的原始 JSON 文档 :

{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}

 

将 HTTP 命令由 ​​PUT​​​ 改为 ​​GET​​​ 可以用来检索文档,同样的,可以使用 ​​DELETE​​​ 命令来删除文档,以及使用 ​​HEAD​​​ 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 ​​PUT​​ 。

精彩评论(0)

0 0 举报