共计 7397 个字符,预计需要花费 19 分钟才能阅读完成。
> 本文最早公布于公众号 极客军营,原文地址
学习 ElasticSearch(后续简称 ES)最好的办法就是多入手实际。在该系列教程中,我会应用“在线书店”这个小我的项目贯通每一个章节。这个我的项目的背景很简略,每本书都有 ISBN、题目 (title)、形容(description)、价格(price)、作者(author)、出版社(publisher) 和库存 (stock) 七个属性,将书的信息存储在 ES 中,用户能够依据书的某些属性信息搜寻想要买的书。
为了能让大家对 ES 整体有一个直观的感触,本节我将率领大家疾速浏览 ES 的各项能力。你刚看到某些概念可能会一头雾水,不过没有关系,本节波及到的所有内容在后续的章节中都有具体介绍,大家对本节中呈现的概念只须要先有个意识即可。
与 ElasticSearch 交互
要应用 ES 提供的服务,首先要晓得如何给 ES 下达指令。ES 服务器提供了一系列的 RESTful API,能够通过HTTP 协定 将数据或指令以 JSON 序列化 的模式发送给 ES 提供的 API 接口。
咱们都晓得,基于 RESTful 格调设计的网络应用应用 GET、POST、PUT、DELETE 四种 HTTP 动词对服务端资源进行操作,其中 GET 用于获取资源,POST 用于新建资源,PUT 用于更新资源,DELETE 用于删除资源。
例如,通过上面的 curl 命令发送 HTTP POST 申请给 ES,保留一本书的信息:
curl -X POST -H "Content-Type: application/json" -d \
'{"title":" 零根底学 Java","description":" 自学 JAVA 的入门图书 ","price": 66.88}' \
http://localhost:9200/book_store/_doc?pretty
该条 curl 命令的执行后果如下图,任何编程语言或工具都能够通过 HTTP 协定调用 ElasticSearch 提供的 RESTful API 接口。
如果咱们每次都通过一长串的 curl 命令调用 ElasticSearch 未免有点繁琐,Kibana 为咱们提供了更不便的操作形式。
在 Kibana 左侧导航栏中,有一个菜单叫做 Dev Tools(开发工具),菜单地位见下图:
应用 Dev Tools 能够让咱们以十分便当的形式操作 ES,例如下图在 Dev Tools 中的操作与上述的 curl 命令完全相同——在 ES 中保留一本书的信息。
相比于应用 curl 命令,在 Kibana Dev Tools 中能够省略对 Content-Type 的申明、ES 服务器的 IP 地址和监听端口。因为这些信息 Kibana 都晓得,会主动帮咱们增加上,就不必咱们额定明确指定了。此外在 Kibana 中输出的命令格局比拟好看,点击箭头 (Click to send request) 就能够间接向 ES 发送命令,并在其右侧显示 Response 后果,应用起来十分不便。
前面所有的示例代码都是在 Kibana 中应用的,即都不须要明确指定 HTTP Header 信息和服务器 IP 地址。
基本概念
在介绍其它内容之前,咱们先来认真看看 ES 返回的 Response:
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "E2lww30BAtxnt_qoQMJz",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 15,
"_primary_term" : 2
}
ES 的 Response 也是 JSON 构造,从其 result 字段能够得悉咱们曾经胜利在 ES 中保留了一本书的信息。此外还有三个须要关注的字段:_index、_type 和_id,它们别离示意索引(Index)、类型(Type)、文档 ID(Document ID)。
- 文档 (Document): 数据读写的最根本单元,在本例中,一本书就对应一个文档。又比方在电商零碎中,一件商品就对应一个文档。在人事零碎中,一名员工也对应一个文档。每个文档都蕴含一个_id 字段,作为文档的标识,它的值在同类型的文档中是惟一的。
- 索引 (Index): 索引是文档的容器,是一类类似文档的汇合,是文档存储的逻辑单元。
- 类型 (Type): 在 ES 的晚期版本,一个索引能够蕴含多个类型,一个类型下蕴含多个文档。但到了 7.0 版本后,一个索引只能有一个类型,且类型的名字必须是_doc。所以目前类型 (Type) 曾经没有什么本质的意义。
咱们将 ElasticSearch 与关系型数据库中的各个概念做一个粗略类比,以便帮忙大家了解:
ElasticSearch | 关系型数据库 |
---|---|
索引(Index)+ 类型(Type) | 表(Table) |
文档(Document) | 行(Row) |
文档字段(Document Field) | 列(Column) |
文档 ID(Document ID) | 主键(Primary Key) |
咱们应用索引 book_store 存储所有图书的信息,上面的 Request 示意在索引 book_store 的_doc 类型下保留一本书的信息(类型也只能是_doc):
POST /book_store/_doc
{
"ISBN": "9787187651807",
"title": "零根底学 Java",
"description": "零根底自学 JAVA 编程的入门图书",
"price": 66.88,
"author": "Poype",
"publisher": "极客军营",
"stock": 55
}
相比于数据库在执行 insert 操作前须要提前创立好对应的表,应用 ES 无需在写入文档前创立好对应的索引。如果写入文档时发现对应的索引不存在,ES 会主动帮咱们创立好那个索引。
因为在保存文档的时候没有提供惟一 ID,ES 会为该文档主动生成一个惟一 ID 作为_id 字段的值。
获取文档数据
能够根据上述的文档 ID 获取一个文档的信息,应用 HTTP GET 办法向 ES 服务器发送查问 Request,在 Request 中明确指定索引和文档 ID。留神这里的文档 ID 是由 ES 随机生成的,所以每次的 ID 都不一样。
GET /book_store/_doc/FWmJw30BAtxnt_qoj8IE
ES 收到该申请后会返回如下 Response:
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj8IE",
"_version" : 1,
"_seq_no" : 16,
"_primary_term" : 2,
"found" : true,
"_source" : {
"ISBN" : "9787187651807",
"title" : "零根底学 Java",
"description" : "零根底自学 JAVA 编程的入门图书",
"price" : 66.88,
"author" : "Poype",
"publisher" : "极客军营",
"stock" : 55
}
}
Response 中蕴含了对该文档阐明的元数据,如咱们曾经介绍过的_index、_type 和_id 三个字段。此外,found 字段为 true 示意胜利找到了对应的文档。_source 字段上面是真正的文档数据。
如果用一个不存在的文档 ID 发动查问会收到上面的 Response,其中 found 字段为 false 示意不存在指定 ID 的文档。
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj81E",
"found" : false
}
批改文档数据
能够依据文档 ID 批改已存在的文档。应用 HTTP PUT 办法发送批改文档的 Request:
PUT /book_store/_doc/FWmJw30BAtxnt_qoj8IE
{
"ISBN": "9787187651807",
"title": "零根底学 Java",
"description": "零根底自学 JAVA 编程的入门图书",
"price": 55.66,
"author": "Poype",
"publisher": "极客军营",
"stock": 55
}
咱们将书的价格从原来的 66.88 批改为 55.66,其它信息放弃不变。ES 收到该申请后返回如下后果:
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj8IE",
"_version" : 2,
"result" : "updated",
"_shards" : {...},
"_seq_no" : 17,
"_primary_term" : 2
}
result 字段为 updated 示意文档曾经更新胜利。另外须要留神的是_version 和_seq_no 两个字段,它们的值都有所增加。这两个字段是用来做并发管制的,具体含意在后续章节会有具体介绍。
删除文档
应用 HTTP DELETE 办法能够删除一个文档,例如删除之前的文档;
DELETE /book_store/_doc/FWmJw30BAtxnt_qoj8IE
ES 收到该申请后返回如下 Response:
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj8IE",
"_version" : 8,
"result" : "deleted",
"_shards" : {...},
"_seq_no" : 23,
"_primary_term" : 2
}
result 字段为 deleted 示意该文档曾经被胜利删除。
全文搜寻
看到这里你兴许会比拟悲观,咱们目前介绍的这些 CRUD 操作任何数据库也都能反对的很好,那么 ES 的劣势是什么呢?别急,上面咱们就来看下,相比于传统数据库,ElasticSeach 所善于的畛域——全文搜寻(Full Text Search)。
为了更好的对其进行阐明,咱们再向 ES 多减少几本书的信息:
POST /book_store/_doc/
{
"ISBN": "9787111213826",
"title": "JAVA 编程思维",
"description": "JAVA 学习经典, 殿堂级著述",
"price": 89.88,
"author": "Bruce Eckel",
"publisher": "机械工业出版社",
"stock": 231
}
POST /book_store/_doc/
{
"ISBN": "9085115891807",
"title": "Python 编程,从入门到实际",
"description": "零根底学 Python 编程教程书籍",
"price": 82.30,
"author": "Eric Matthes",
"publisher": "人民邮电出版社",
"stock": 121
}
POST /book_store/_doc/
{
"ISBN": "9787115449153",
"title": "Elasticsearch 实战",
"description": "Elasticsearch 入门教程书籍",
"price": 79,
"author": "Radu Gheorghe",
"publisher": "人民邮电出版社",
"stock": 87
}
POST /book_store/_doc/
{
"ISBN": "9787115472588",
"title": "鸟哥的 Linux 私房菜",
"description": "实用 Linux 零碎利用、开发及运维人员",
"price": 98.80,
"author": "鸟哥",
"publisher": "人民邮电出版社",
"stock": 77
}
例如一位顾客想搜寻一本对于 Java 的书。如果是应用关系型数据库,你可能会执行相似上面的 SQL 帮忙顾客找到想要的书;
select * from book_store where title like %Java%;
这条 SQL 的性能很差,须要扫描整个表。而且兼容性也不好,例如书名中蕴含 java 和 JAVA 的都无奈被检索到。
换作 ElasticSearch,能够应用如下的查问命令搜寻 Java 相干的书籍:
GET /book_store/_doc/_search
{
"query": {
"match": {"title": "java"}
}
}
ElasticSearch 收到该申请后返回如下后果:
{
"took" : 619,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.9278223,
"hits" : [
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "GGmpw30BAtxnt_qoXMJq",
"_score" : 0.9278223,
"_source" : {
"ISBN" : "9787111213826",
"title" : "JAVA 编程思维",
"description" : "JAVA 学习经典, 殿堂级著述",
"price" : 89.88,
"author" : "Bruce Eckel",
"publisher" : "机械工业出版社",
"stock" : 231
}
},
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj8IE",
"_score" : 0.9278223,
"_source" : {
"ISBN" : "9787187651807",
"title" : "零根底学 Java",
"description" : "零根底自学 JAVA 编程的入门图书",
"price" : 55.66,
"author" : "Poype",
"publisher" : "极客军营",
"stock" : 55
}
}
]
}
}
能够看到 Response 中曾经蕴含了咱们想要的后果。它的兼容性很好,在书名中蕴含 Java 或 JAVA 的文档都能被胜利搜寻到。它的性能也很高,即便是很大量的数据,ElasticSearch 也能够很快为用户搜寻到想要的数据。
更简单的搜寻
如果有一位顾客,他想买一本学习 Java 的书,然而他的估算无限,最多只能付 70 元。所以他想检索 Java 相干的书籍,且书的售价必须小于 70 元。相似的搜寻场景在咱们日常生活中很常见,能够通过如下命令实现这个搜寻需要,其中的”lt“示意小于(less than):
GET /book_store/_doc/_search
{
"query": {
"bool": {
"filter": {
"range": {
"price": {"lt": 70}
}
},
"must": {
"match": {"title": "java"}
}
}
}
}
ES 收到该申请后返回如下后果:
{
"took" : 320,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9278223,
"hits" : [
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "FWmJw30BAtxnt_qoj8IE",
"_score" : 0.9278223,
"_source" : {
"ISBN" : "9787187651807",
"title" : "零根底学 Java",
"description" : "零根底自学 JAVA 编程的入门图书",
"price" : 55.66,
"author" : "Poype",
"publisher" : "极客军营",
"stock" : 55
}
}
]
}
}
高亮匹配片段
如果又有一位顾客,他心愿找一本经典著作。咱们能够通过搜寻书的形容 (description) 中含有“经典”二字的文档实现这个需要。
但该顾客不仅心愿能获取到搜寻后果,还心愿可能一眼看出为什么返回给他后果合乎他的要求。个别能够通过在搜寻后果中把关键字加高亮以便让用户一眼就能辨认到。
GET /book_store/_doc/_search
{
"query": {
"match": {"description": "经典"}
},
"highlight": {
"fields": {"description": {}
}
}
}
咱们在搜寻命令中用 highlight 指定了高亮字段的名称,ElasticSearch 收到该申请后返回如下后果:
{
...
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.8796844,
"hits" : [
{
"_index" : "book_store",
"_type" : "_doc",
"_id" : "GGmpw30BAtxnt_qoXMJq",
"_score" : 2.8796844,
"_source" : {
"ISBN" : "9787111213826",
"title" : "JAVA 编程思维",
"description" : "JAVA 学习经典, 殿堂级著述",
"price" : 89.88,
"author" : "Bruce Eckel",
"publisher" : "机械工业出版社",
"stock" : 231
},
"highlight" : {
"description" : ["JAVA 学习 <em> 经 </em><em> 典 </em>, 殿堂级著述"]
}
}
]
}
}
相比于之前的搜寻后果,这次在 Response 中还蕴含 highlight 字段。其中应用 html 标签 给匹配的关键字加高亮。但这个高亮加的不是很失当,相比于“经 典”,“经典”这种高亮形式才更加正当。大家这里先有个印象,等前面咱们学了分词器,大家就晓得该如何优化这个问题了。
小结
本章通过一个小示例,带大家疾速浏览了 ElasticSearch 中的一些基本概念。咱们理解了如何与 ElasticSearch 服务器交互、如何通过 Kibana 更不便的操作 ElasticSearch、如何执行根本的 CRUD 操作、以及如何实现简略的搜寻需要。上面的章节将正式为大家具体介绍 ElasticSearch 的各项技术细节。
喜爱本文的敌人,欢送关注公众号 极客军营,收看更多精彩内容