上一篇文章中我们已经启动Elasticsearch了,接下来我们就可以与Elasticsearch进行通信,例如插入数据、检索数据、删除数据等等。Elasticsearch 提供了Java API和RESTful API 两种方式来与之通信。
Java API
如果你使用的是 JAVA,Elasticsearch 内置了两个客户端,你可以在你的代码中使用:
节点客户端: 节点客户端以一个 无数据节点 的身份加入了一个集群。换句话说,它自身是没有任何数据的,但是他知道什么数据在集群中的哪一个节点上,然后就可以请求转发到正确的节点上并进行连接。
传输客户端: 更加轻量的传输客户端可以被用来向远程集群发送请求。他并不加入集群本身,而是把请求转发到集群中的节点。
这两个客户端都使用 Elasticsearch 的 传输 协议,通过9300端口与 java 客户端进行通信。集群中的各个节点也是通过9300端口进行通信。如果这个端口被禁止了,那么你的节点们将不能组成一个集群。
注意事项
Java 的客户端的版本号必须要与 Elasticsearch 节点所用的版本号一样,不然他们之间可能无法识别。
更多关于 Java API 的说明可以在这里找到 Guide
通过 HTTP 向 RESTful API 传送 json
其他的语言可以通过9200端口与 Elasticsearch 的 RESTful API 进行通信。事实上如你所见,你甚至可以使用行命令 curl 来与 Elasticsearch 通信。
向 Elasticsearch 发出的请求和其他所有的 HTTP 请求的组成部分是一致的。例如,计算集群中文件的数量,我们就可以使用:
curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}
'
- 相应的 HTTP 请求方法 或者 变量 : GET, POST, PUT, HEAD 或者 DELETE。
- 集群中任意一个节点的访问协议、主机名以及端口。
- 请求的路径。
- 任意一个查询后再加上 ?pretty 就可以生成 更加美观 的JSON反馈,以增强可读性。
- 一个 JSON 编码的请求主体(如果需要的话)。
Elasticsearch 将会返回一个 HTTP 状态码类似于 ‘200 OK’,以及一个 JSON 格式的主体(除了单纯的 ‘HEAD’ 请求),上面的请求会得到下方的 JSON 主体:
{
"count" : 0,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
}
}
在反馈中,我们并没有看见 HTTP 的头部信息,因为我们没有告知 curl 显示这些内容。如果你想看到头部信息,可以在使用 curl 命令的时候再加上 -i 这个参数:
curl -i -XGET 'http://localhost:9200/_count'
基本概念
Elasticsearch 是 面向文档型数据库,这意味着它存储的是整个对象或者 文档,它不但会存储它们,还会为他们建立索引,这样你就可以搜索他们了。你可以在 Elasticsearch 中索引、搜索、排序和过滤这些文档。不需要成行成列的数据。这将会是完全不同的一种面对数据的思考方式,这也是为什么 Elasticsearch 可以执行复杂的全文搜索的原因。
Elasticsearch使用 JSON (或称作JavaScript Object Notation ) 作为文档序列化的格式。JSON 已经被大多数语言支持,也成为 NoSQL 领域的一个标准格式。它简单、简洁、易于阅读。
例如我们有一个User对象,我们可以构造这样的一个 JSON对象:
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"about": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01",
}
虽然 user 这个对象非常复杂,但是它的结构和含义都被保留到 JSON 中了。在 Elasticsearch 中,将对象转换为 JSON 并作为索引要比在表结构中做相同的事情简单多了。
在 Elasticsearch 中,文档属于一种 类型(type),各种各样的类型存在于一个 索引 中。你也可以通过类比传统的关系数据库得到一些大致的相似之处:
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引 ⇒ 类型 ⇒ 文档 ⇒ 字段(Fields)
一个 Elasticsearch 集群可以包含多个 索引(数据库),也就是说其中包含了很多 类型(表)。这些类型中包含了很多的 文档(行),然后每个文档中又包含了很多的 字段(列)。
易混淆点
索引这个词汇已经被赋予了太多意义,所以在这里我们有必要澄清一下:
- 索引 (名词)
如上文所说,一个 索引 就类似于传统关系型数据库中的 数据库。这里就是存储相关文档的的地方。
- 索引 (动词)
为一个文档创建索引 是把一个文档存储到一个索引(名词)中的过程,这样它才能被检索。这个过程非常类似于 SQL 中的 INSERT
命令,如果已经存在文档,新的文档将会覆盖旧的文档。
- 反向索引
在关系数据库中的某列添加一个 索引,比如多路搜索树(B-Tree)索引,就可以加速数据的取回速度, Elasticsearch 以及
Lucene 使用的是一个叫做 反向索引(inverted index) 的结构来实现相同的功能。
示例
想象我们正在为一个名叫 megacorp 的公司的 HR 部门制作一个新的员工名单系统,这些名单应该可以满足实时协同工作,所以它应该可以满足以下要求:
- 数据可以包含多个值的标签、数字以及纯文本内容。
- 可以检索任何职员的所有数据。
- 允许结构化搜索。例如,查找30岁以上的员工。
- 允许简单的全文搜索以及相对复杂的短语搜索。
- 在返回的匹配文档中高亮关键字。
- 拥有数据统计与管理的后台。
数据存储
第一步就是存储员工的数据。这样你就需要一个“员工档案”的表单,这样每个文档都代表着一个员工。在 Elasticsearch 中,每个文档都属于一种 类型(type),各种各样的类型存在于一个 索引 中。
所以为了创建员工名单,我们需要进行如下操作:
- 为每一个员工的 文档 创建索引,每个 文档 都包含了一个员工的所有信息。
- 每个文档都会被标记为 employee 类型。
- 这种类型将存活在 megacorp 这个 索引 中。
- 这个索引将会存储在 Elasticsearch 的集群中
在实际的操作中,这些操作是非常简单的(即使看起来有这么多步骤)。我们可以把如此之多的操作通过一个命令来完成:
curl -XPUT 'http://localhost:9200/megacorp/employee/1' -d '
{
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
],
"join_time": "2014-11-24"
}'
注意在 /megacorp/employee/1 路径下,包含了三个部分:
名字 | 内容 |
---|---|
megacorp | 索引的名字 |
employee | 类型的名字 |
1 | 当前员工的ID |
请求部分,也就是 JSON 文档,在这里包含了关于这名员工的所有信息。他的名字是 “Douglas Fir”,他已经25岁了,他很喜欢攀岩。
我们在操作前不需要进行任何管理操作,Elasticsearch 会自动检测数据结构和类型、创建索引 并让其能够被搜检索,所有的一切操作已经在后台被默默地完成了,非常简单吧!
在进行下一步之前,我们再为这个目录添加更多的员工信息吧:
curl -XPUT 'http://localhost:9200/megacorp/employee/2' -d '
{
"first_name" : "Jane",
"last_name" :