本文是对Elasticsearch官方权威指南的学习。
Elasticsearch是一个基于Apache Lucene™的开源搜索引擎,它使用Java
开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API
来隐藏Lucene的复杂性,从而让全文搜索变得简单。关于Elasticsearch:
RESTful API
,因此它可以被各种语言客户端使用,也可以直接通过curl
命令行直接使用。由于Elasticsearch是使用java开发的,因此在安装之前,需要确保已经搭建了JDK环境。
从https://www.elastic.co/cn/downloads/elasticsearch Elasticsearch官网下载Elasticsearch安装包进行安装。
./bin/elasticsearch
bin\elasticsearch.bat
在另一个终端执行:
curl 'http://localhost:9200/?pretty'
在windows下可以先安装一下curl
命令,同时windows执行该语句会报错。
建议安装一个Cygwin,可以解决不能执行的错误。
上面我们运行的Elasticsearch实例就是一个节点
,而集群(cluster)
是一组具有相同cluster.name
的节点集合,他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。通过修改config/
目录下的elasticsearch.yml
文件,然后重启ELasticsearch来配置集群,Elasticsearch可以通过API关闭:
curl -XPOST 'http://localhost:9200/_shutdown'
Elasticsearch提供了基于HTTP协议,以JSON为数据交互格式的RESTful API,所有的语音都可以通过9200
端口,使用RESTful API
与Elasticsearch进行通信,甚至可以通过curl
命令与Elasticsearch通信。
Elasticsearch请求格式:
curl -X '://:/?' -d ''
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
与关系型数据库的存储不同,Elasticsearch使用JSON作为文档序列化格式,有着简洁、简单且容易阅读的优势。例如一下JSON表示一个用户对象:
{
"email": "[email protected]",
"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"
}
在Elasticsearch中,索引(index)
就像是传统关系数据库中的数据库,它是相关文档存储的地方。默认情况下,文档中的所有字段都会被索引(拥有一个倒排索引),只有这样他们才是可被搜索的。Elasticsearch使用文档来存储数据,文档归属于一种类型(type),而这些类型存在于索引(index)中,类比关系型数据库则有以下关系:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。
创建员工目录,我们将进行如下操作:
curl -X PUT 'http://localhost:9200/megacorp/employee/3' -d '{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}'
执行这段指令时,会报错:
此时,需要指定相应的头部信息,才可以解决错误:
curl -H "Content-Type: application/json" -X PUT 'http://localhost:9200/megacorp/employee/3' -d '{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}'
名字 | 说明 |
---|---|
megacorp | 索引名 |
employee | 类型名 |
1 | 这个员工的ID |
请求实体(JSON文档),包含了这个员工的所有信息。
现在,我们可以检索单个员工的信息,可以通过HTTP GET请求并指出文档的“地址”(索引、类型和ID),根据这三部分信息,我们就可以返回原始JSON文档。这个操作类似于SQL的where语句精准匹配。
curl -X GET 'http://localhost:9200/megacorp/employee/2'
通过简单搜索,我们可以不加上文档ID,就可以返回对应索引和类型的搜索结果。使用megacorp索引和employee类型,但是我们在结尾使用关键字_search
来取代原来的文档ID。响应内容的hits
数组中包含了我们所有的三个文档。默认情况下搜索会返回前10个结果。
curl -X GET 'http://localhost:9200/megacorp/employee/_search'
结果:
添加查询字符串,搜索姓氏中包含“Smith”的员工,我们要像传递URL参数一样去传递查询语句:
curl -X GET 'http://localhost:9200/megacorp/employee/_search?q=last_name:Smith'
在请求中依旧使用_search
关键字,然后将查询语句传递给参数q=
,结果:
上述的搜索都没有什么特别的地方,通过sql也可以实现,Elasticsearch特殊之处在于提供丰富且灵活的查询语言叫做DSL查询(Query DSL)
,它允许你构建更加复杂、强大的查询。
DSL(Domain Specific Language特定领域语言)
以JSON请求体的形式出现。
例如,以下DSL,等同于查询字符串的搜索。
curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}'
我们依旧想要找到姓氏为“Smith”的员工,但是我们只想得到年龄大于30岁的员工。
curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}'
全文搜索是传统数据库搞不定的任务。
curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}'
结果:
Elasticsearch 默认按照相关性得分排序,即每个文档跟查询的匹配程度。第一个最高得分的结果很明显:John Smith 的 about 属性清楚地写着 “rock climbing” 。
但为什么 Jane Smith 也作为结果返回了呢?原因是她的 about 属性里提到了 “rock” 。因为只有 “rock” 而没有 “climbing” ,所以她的相关性得分低于 John 的。
注:
Elasticsearch中的 相关性 概念非常重要,也是完全区别于传统关系型数据库的一个概念,数据库中的一条记录要么匹配要么不匹配。
在全文搜索中,about中提到rock的Jane Smith对象也被返回了,如果我们想要精确匹配一系列单词或者_短语_。 比如, 我们想执行这样一个查询,仅匹配同时包含 “rock” 和 “climbing” ,并且 二者以短语 “rock climbing” 的形式紧挨着的雇员记录。使用以下语句:
curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}'
高亮出关键部分,让用户知道为何该文档符合查询条件。
curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}'