一、elasticsearch基本概念
在开始学习ES之前,我们需要对其有个大概的了解,理解ES的优势和概念,浅析ES的使用场景和弊端。知道了这些,将会对后续的学习过程有莫大的帮助。
简介
ElasticSearch是一个开源的分布式搜索引擎,具备高可靠性,支持非常多的企业级搜索用例。像Solr4一样,是基于Lucene构建的。支持时间时间索引和全文检索。它对外提供一系列基于java和http的api,用于索引、检索、修改大多数配置。 它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布。更多内容可以访问其官网:http://www.elasticsearch.org
基本概念
- NRT(Near Real Time)
近实时,ES中索引一个文档到其被搜索到只有很小的延迟(大概1s) - cluster
代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。 - shards
代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。 - river
代表es的一个数据源,也是其它存储方式(如:数据库)同步数据到es的一个方法。它是以插件方式存在的一个es服务,通过读取river中的数据并把它索引到es中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia的。 - Transport
代表es内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。 - node
一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点。 - index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。 - replicas
代表索引副本,es可以设置多个索引的副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高es的查询效率,es会自动对搜索请求进行负载均衡。
Lucene
Elasticsearch底层是基于Lucene的,Lucene是一款优秀的搜索lib, 文档是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,而域的值则是真正被搜索的内容。每个域都有其标识名称,通常为一个文本值或二进制值。将文档加入索引中时,需要首先将数据转换成Lucene能识别的文档和域,域值是被搜索的对象。例如,用户输入搜索内容“title:elasticsearch”时,则表示搜索“标题”域值中包含单词“elasticsearch”的所有文档。
Lucene关键概念:
- Document:用来索引和搜索的主要数据源,包含一个或者多个Field,而这些Field则包含我们跟Lucene交互的数据。
- Field:Document的一个组成部分,有两个部分组成,name和value。
- Term:不可分割的单词,搜索最小单元。
- Token:一个Term呈现方式,包含这个Term的内容,在文档中的起始位置,以及类型。
Lucene使用Inverted index来存储term在document中位置的映射关系。
譬如如下文档:
Elasticsearch Server 1.0 (document 1)
Mastring Elasticsearch (document 2)
Apache Solr 4 Cookbook (document 3)
使用inverted index存储,一个简单地映射关系:
Term | Count | Docuemnt |
---|---|---|
1.0 | 1 | <1> |
4 | 1 | <3> |
Apache | 1 | <3> |
Cookbook | 1 | <3> |
Elasticsearch | 2 | <1>.<2> |
Mastering | 1 | <2> |
Server | 1 | <1> |
Solr | 1 | <3> |
对于上面例子,我们首先通过分词算法将一个文档切分成一个一个的token,再得到该token与document的映射关系,并记录token出现的总次数。这样就得到了一个简单的inverted index。
二、ES安装
依赖环境
最新版本的ES5.5+需要Java8及以上版本,建议是Oracle JDK 1.8.0_131版本,我们可以在Oracle下载最新版本JAVA8.然后进行安装
在apt中增加java的PPA
sudo add-apt-repository -y ppa:webupd8team/java
更新apt:
sudo apt-get update
安装最新稳定版Oracle Java 8
sudo apt-get -y install oracle-java8-installer
本教程使用ES2.3.0,需要java7级以上,通过java -version
或echo $JAVA_HOME
查看版本。
如果在WIN环境下安装ES,请下载CURL和cygwin。
安装
一旦我们将Java安装完成,我们就可以下载并安装Elasticsearch了。其二进制文件可以从www.elasticsearch.org/download这里下载,你也可以从这里下载以前发布的版本。对于每个版本,你可以在zip、tar、DEB、RPM类型的包中选择下载。笔者下载的是ES2.3的DEB包。下载完成后,运行sudo dpkg -i elasticsearch-2.3.deb
安装。
ES默认安装路径在/usr/share下,文件夹中的config保存配置文件,plugin保存插件,bin下是可执行文件。
先为elasticsearch文件夹获取权限:
sudo chmod -R 775 /usr/share/elasticsearch
运行bin/elasticsearch
开启ES服务,打开浏览器http://127.0.0.1:9200/
就可以看到以json格式保存的ES服务信息。
你可以自行修改配置文件,配置文件:config/elasticsearch.yml,/etc/default/elasticsearch。每个配置参数的字面意思也好理解,不再赘述。具体的参数是什么作用,也可以查询官网文档。
head插件安装
elasticsearch-head是一个elasticsearch的集群管理工具,它是完全由HTML5编写的独立网页程序,你可以通过插件把它集成到es
1. elasticsearch/bin/plugin -install mobz/elasticsearch- head
2. 运行es
3. 打开http://localhost:9200/_plugin/head/
head插件在/usr/share/下,所以需要为该文件夹及子文件夹赋予修改执行权限chmod -R 775 /usr/share/elastcsearch/
,否则会报错。
基本操作
集群健康
让我们以基本的健康检查作为开始,我们可以利用它来查看我们集群的状态。此过程中,我们使用curl,当然,你也可以使用任何可以创建HTTP/REST调用的工具。我们假设我们还在我们启动Elasticsearch的节点上并打开另外一个shell窗口。
要检查集群健康,我们将使用_cat API。需要事先记住的是,我们的节点HTTP的端口是9200:curl 'localhost:9200/_cat/health?v'
-列出所有的索引
让我们看一下我们的索引:curl 'localhost:9200/_cat/indices?v'
响应是:
curl 'localhost:9200/_cat/indices?v' health index pri rep docs.count docs.deleted store.size pri.store.size
这个结果意味着,在我们的集群中,我们没有任何索引。
创建一个索引
现在让我们创建一个叫做“customer”的索引,然后再列出所有的索引:curl -XPUT 'localhost:9200/customer?pretty' curl 'localhost:9200/_cat/indices?v'
第一个命令使用PUT创建了一个叫做“customer”的索引。我们简单地将pretty附加到调用的尾部,使其以美观的形式打印出JSON响应(如果有的话)。
第二个命令的结果告知我们,我们现在有一个叫做customer的索引,并且它有5个主分片和1份复制(都是默认值),其中包含0个文档。
你可能也注意到了这个customer索引有一个黄色健康标签。回顾我们之前的讨论,黄色意味着某些复制没有(或者还未)被分配。这个索引之所以这样,是因为Elasticsearch默认为这个索引创建一份复制。由于现在我们只有一个节点在运行,那一份复制就分配不了了(为了高可用),直到当另外一个节点加入到这个集群后,才能分配。一旦那份复制在第二个节点上被复制,这个节点的健康状态就会变成绿色。
索引并查询一个文档
现在让我们放一些东西到customer索引中。首先要知道的是,为了索引一个文档,我们必须告诉Elasticsearch这个文档要到这个索引的哪个类型(type)下。让我们将一个简单的客户文档索引到customer索引、“external”类型中,这个文档的ID是1,操作如下:
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d ' { "name": "John Doe" }'
响应如下:
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d ' { "name": "John Doe" }' { "_index" : "customer", "_type" : "external", "_id" : "1", "_version" : 1, "created" : true }
从上面的响应中,我们可以看到,一个新的客户文档在customer索引和external类型中被成功创建。文档也有一个内部id 1, 这个id是我们在索引的时候指定的。
有一个关键点需要注意,Elasticsearch在你想将文档索引到某个索引的时候,并不强制要求这个索引被显式地创建。在前面这个例子中,如果customer索引不存在,Elasticsearch将会自动地创建这个索引。
现在,让我们把刚刚索引的文档取出来:
curl -XGET 'localhost:9200/customer/external/1?pretty'
响应如下:
curl -XGET 'localhost:9200/customer/external/1?pretty' { "_index" : "customer", "_type" : "external", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "name": "John Doe" } }
除了一个叫做found的字段来指明我们找到了一个ID为1的文档,和另外一个字段——_source——返回我们前一步中索引的完整JSON文档之外,其它的都没有什么特别之处。
删除一个文档
现在让我们删除我们刚刚创建的索引,并再次列出所有的索引:
curl -XDELETE 'localhost:9200/customer?pretty' curl 'localhost:9200/_cat/indices?v'
响应如下:
curl -XDELETE 'localhost:9200/customer?pretty' { "acknowledged" : true } curl 'localhost:9200/_cat/indices?v' health index pri rep docs.count docs.deleted store.size pri.store.size
这表明我们成功地删除了这个索引,现在我们回到了集群中空无所有的状态。
在更进一步之前,我们再细看一下一些我们学过的API命令:
curl -XPUT 'localhost:9200/customer' curl -XPUT 'localhost:9200/customer/external/1' -d ' { "name": "John Doe" }' curl 'localhost:9200/customer/external/1' curl -XDELETE 'localhost:9200/customer'
如果我们仔细研究以上的命令,我们可以发现访问Elasticsearch中数据的一个模式。这个模式可以被总结为:
curl -<REST Verb> <Node>:<Port>/<Index>/<Type><ID>
这个REST访问模式普遍适用于所有的API命令,如果你能记住它,你就会为掌握Elasticsearch开一个好头。
- 修改你的数据
Elasticsearch提供了近乎实时的数据操作和搜索功能。默认情况下,从你索引/更新/删除你的数据动作开始到它出现在你的搜索结果中,大概会有1秒钟的延迟。这和其它类似SQL的平台不同,数据在一个事务完成之后就会立即可用。
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "John Doe"
}'
- 更新文档
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"doc": { "name": "Jane Doe" }
}'
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"script" : "ctx._source.age += 5"
}'
- 删除文档
curl -XDELETE
- 批处理
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
载入样本数据
你可以从https://github.com/bly2k/files/blob/master/accounts.zip?raw=true下载这个样本数据集。将其解压到当前目录下,如下,将其加载到我们的集群里:curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json curl 'localhost:9200/_cat/indices?v'
响应为
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open bank 5 1 1000 0 442.1kb 442.1kb
yellow open customer 5 1 0 0 795b 795b
yellow open dept 5 1 1 0 3.6kb 3.6kb
这意味着我们成功批量索引了1000个文档到银行索引中(account类型)。搜索REST
curl 'localhost:9200/bank/_search?q=*&pretty'
我们仔细研究一下这个查询调用。我们在bank索引中搜索(_search端点),并且q=*参数指示Elasticsearch去匹配这个索引中所有的文档。pretty参数,和以前一样,仅仅是告诉Elasticsearch返回美观的JSON结果。
- 更多
关于更多api的使用,可以查看官方文档https://www.elastic.co/guide/en/elasticsearch/reference/2.3/index.html