ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
es作为一款稳定、可靠、高效的可分布式部署的NoSql数据库,在企业应用中主要用于搜索引擎、数据收集与分析各个方面,作为数据库,那么在数据安全、查询、备份与恢复、数据分析上具体都是如何保证,在es中如何实现。
因为以前没有使用过,所以此次基于学习的基础上,一步一步完成其基础的认识与使用,主要从以下几个方面:
1、安装
进入到官网 https://www.elastic.co/cn/downloads/elasticsearch,根据自己的系统,下载对应系统安装包,目前下载最新版本elasticsearch-7.1.1,因为各个版本上存在一些差异,此次下载Elasticsearch 5.6.16学习,我们可以打开历史版本进行查看下载,
进去之后下载,由于我的是win10系统,下载zip类型的安装包,将该文件下载后压到指定目录,进入 bin,不需要任何配置双击elasticsearch.bat即可运行:
在浏览器输入 http://localhost:9200/ 显示如下信息:
说明已经正常启动。
2、说明
在正式使用前,有必要对elasticsearch一些相关的名称概念做一些了解,这样在之后的操作中,方便我们理解与使用:
集群(Cluster):ES可以单节点运行,但是为了保证其可靠性与容错性,一般会部署多个ES服务,而这些关联的服务组成一个集群服务。
节点(Node):一个集群中的每个ES服务则是一个节点,节点可以在一台或多台服务器上,但是为了保证各个节点的可靠性,一般会将每个节点部署到不同服务器上,而集群是由拥有相同集群名称的节点构成(默认名称为elasticsearch),而每个节点由有各自不同的名称(默认会由不同的漫威人物名称)。只要有需要,一个集群可以拥有任意多的节点。节点承担了数据存储、索引与查询。
节点有以下类型:
a、主节点:主节点不接受客户端的请求,他主要控制Elasticsearch集群,负责集群中的操作,比如创建/删除一个索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。主节点处理集群的状态并广播到其他节点,并接收其他节点的确认响应。 默认情况下任何一个集群中的节点都有可能被选为主节点,每个节点都可以通过设定配置文件elasticsearch.yml中的node.master属性为true(默认),node.data属性设置为false,成为主节点。对于大型的生产集群来说,推荐使用一个专门的主节点来控制集群,该节点将不处理任何用户请求,稳定的主节点对集群的健康是非常重要的。
b、数据节点:该节点具有存储数据和执行数据相关的操作,如增删改查,搜索,和聚合操作。数据节点对cpu,内存,io要求较高,在优化的时候需要监控数据节点的状态,当资源不够的时候,需要在集群中添加新的节点。默认情况下,每个节点都可以通过设定配置文件elasticsearch.yml中的node.data属性为true(默认)成为数据节点。如果我们要使用一个专门的主节点,应将其node.data属性设置为false。
c、客户端节点:该节点主要将客户端的请求路由到集群中的各个节点,扮演一个负载均衡的角色。将node.master属性和node.data属性都设置为false,那么该节点就是一个客户端节点。
d、部落节点:部落节点可以跨越多个集群,它可以接收每个集群的状态,然后合并成一个全局集群的状态,它可以读写所有节点上的数据,部落节点在elasticsearch.yml中的配置如下:tribe:*:
索引(Index):一个索引就是一个拥有相似特征的文档的集合。比如说,你可以有一个产品的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。索引类似于关系型数据库中Database的概念。在一个集群中,如果你想,可以定义任意多的索引。
类型(Type):在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型。类型类似于关系型数据库中Table的概念。从Elasticsearch 6.x版本已经删除了type,或者说是一个索引只会对应一个类型。当然在5.x版本中可以通过配置项来完成。
文档(Document):文档是由多属性构成的数据集合(以JSON格式来表示),一个文档是一个可被索引的最基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,在一个index/type里面,只要你想,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。文档类似于关系型数据库中Record的概念。实际上一个文档除了用户定义的数据外,还包括_index
、_type
和_id
字段。
分片(Shade):一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。
为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。 分片之所以重要,主要有两方面的原因:
至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了。这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。复制之所以重要,主要有两方面的原因:
副本(Replia):每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制数量,但是不能改变分片的数量。
默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。一个索引的多个分片可以存放在集群中的一台主机上,也可以存放在多台主机上,这取决于你的集群机器数量。主分片和复制分片的具体位置是由ES内在的策略所决定的。
映射(Mapping):上面说到文档是属性的稽核,而映射类型也就是为文档属性定义数据类型,一个索引可以一个或者多个类型。每一个映射类型包括:
映射包括动态映射与静态映射,其中静态映射是在建立所以时指定数据类型,而动态映射则会在数据插入时自动设置对应的数据类型。
注意:相同索引,但是类型不同,而名字相同的字段的数据类型必须一致,即拥有相同的映。
3、配置
在安装目录下config/elasticsearch.yml可以对elasticsearch进行配置,学习时可以使用默认配置启动。
略
4、使用
在使用前,为了方便之后的操作与可视化,首先下载elasticsearch-head插件,地址https://github.com/mobz/elasticsearch-head,下载完成后解压到指定目录,结构如下:(当然你也可以安装chrome插件)
然后就是安装与启动插件了,这个依赖于npm,电脑首先需要安装nodejs并配置环境。进入目录后我们执行下面的命令
npm install
//需要等待一些时间
npm run start
//见到如下信息
> elasticsearch-head@0.0.0 start E:\tools\elasticsearch-cluster\elasticsearch-head-5.0.0
> grunt server
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100
在浏览器中输入 localhost:9100出现如下界面:
如果一直无法连接,你需要在elasticsearch.yml配置文件中加上:
http.cors.enabled: true
http.cors.allow-origin: "*"
接下来就是基本的操作了:
在之前还是需要一些准备的工作,我们可以通过刚才的head插件,完成以下的操作,当然,ES提供了RESTFul的API供我们调用,我们可以使用一些工具来辅助完成下面的操作,比如curl命令,这个可能你需要安装一些额外的终端,比如cygwin64;或者我们直接使用postman,下面的操作都是基于postman来完成。具体的数据变化,需要通过head插件自行查看。
1、新建
请求:
PUT localhost:9200/commodity
参数:
{
"settings":{
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
}
这样就完成了商品的创建,索引为commodity,分片为3,副本为1。
2、删除
请求:
DELETE localhost:9200/commodity
类型的定义在创建索引是完成:
PUT localhost:9200/commodity
{
"settings":{
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
},
"mappings":{
"electrical":{
"properties":{
"name":{ "type":"text" },
"manufacturer":{ "type":"keyword" },
"price":{ "type":"integer" },
"date":{ "type":"date" }
}
},
"daily":{
}
}
}
定义了家用电器与日用品两个类型,其中家用电器使用了静态类型映射,而日用品使用了动态映射。
1、新增
PUT localhost:9200/commodity/electrical/1
{
"name":"电视机",
"manufacturer":"长虹",
"price":3411,
"date":"2018-01-01"
}
2、修改
POST localhost:9200/commodity/electrical/1/_update
{
"doc":{
"price":3800
}
}
或根据脚本修改:
{
"script":{
"lang":"painless",
"inline":"ctx._source.price += 50"
}
}
3、查询
//简单查询 根据主键查询
GET localhost:9200/commodity/electrical/1
//条件查询 根据属性查询
POSTS localhost:9200/commodity/_search
{
"query":{
"match_all":{},
"_source":["name","price"]//指定结果
}
}
http://localhost:9200/commodity/electrical/_search?q=name:电视
POST localhost:9200/commodity/_search
{
"query":{
"match":{
"name":"电视机"
}
},
"sort":[{"date":{"order":"desc"}}],
"from":1,
"size":10
}
//聚合查询 针对属性做运算查询 terms,stats,max...
POSTS localhost:9200/commodity/_search
{
"aggs":{
"agg_by_price":{
"terms":{
"field":"price"
}
}
}
}
4、删除
DELETE localhost:9200/commodity/electrical/1
5、扩展
ES作为一种数据库,提供了各种方式来对数据进行快速查询。
子条件查询: POST localhost:9200/commodity/_search { "query":{ //全文查询,分词 "match":{ "name":"电视机" } //全文查询,习语 "match_phrase":{ name:"电视机" }, //多条件 "multi_match":{ "query":"电视", "fields":["name",""] }, //条件 "query_string":{ query:"电视机 OR 长虹" }, //字段 "term":{ "name":"电视机" }, //范围 "range":{ "date":{ "gte":"2018-01-01", "let":"2018-04-21" } } } } POST localhost:9200/commodity/_search { "query":{ "bool":{ "filter":{ "term":{ "name":"电视机" } } "should":[ { "match":{ "name":"" } } ], "must":[ { "match":{ "name":"" } } ] } "constant_score":{ "filter":{ "match":{ "name":"电视机" } }, "boost":2 } } }
6、总结
#API
新建索引
PUT localhost:9200/<index>
{
"settings":{
"index" : {
"number_of_shards" : <分配数量>,
"number_of_replicas" : <副本数量>
}
},
"mappings":{
"<type>":{
"properties":{
"<属性名>":{
"type":"text|keyword|integer|date|...." ,
"index":"true",
"analyzer":"<>",
"formate":""
...
}
}
}
}
}
删除索引
DELETE localhost:9200/<index>
新建文档
PUT localhost:9200/<index>/<type>/<id>
{
"<属性名>":"<属性值>"
}
修改文档
POST localhost:9200/<index>/<type>/<id>/_update
通过json修改:
{
"doc":{
"<属性名>":<属性值>
}
}
通过脚本修改:
{
"script":{
"lang":"<语言>",
"inline":"<脚本>",
"params":{
"<参数名>":"<参数值>"
}
}
}
删除文档:
DELETE localhost:9200/<index>/<type>/<id>
查询文档
//根据id查询
GET localhost:9200/<index>/<type>/<id>
//根据属性查询
GET localhost:9200/<index>/<type>/_search?q=<属性名>:<属性值>
//属性匹配查询
POST localhost:9200/<index>/_search
{
"query":{
"match":{
"<属性名>":"<属性值>"
}
},
"sort":[{"<属性名>":{"order":"desc"}}],
"from":1,
"size":10,
"highlight": {
"fields": {
"<属性名>": {
"type": "plain"
}
}
}
}
//聚合查询 对结果集运算做运算查询 terms,stats,max...
POST localhost:9200/<index>/_search
{
"aggs":{
"agg_by_price":{
"terms|stats|min|max|...":{
"field":"<属性名>"
}
}
}
}
{
"query":{
//全文查询,分词|习语
"match|match_phrase|":{
"<属性名>":"<属性值>"
},
//多条件
"multi_match":{
"query":"<属性值>",
"fields":["<属性名>"...]
},
//条件
"query_string":{
"query":"<属性值> OR <属性值> AND <<属性值>>"
},
//字段
"term":{
"<属性名>":"<属性值>"
},
//范围
"range":{
"<属性名>":{
"gte":"<属性值>",
"let":"<属性值>"
}
}
}
}
{
"query":{
"bool":{
"filter":{
"term|should|must":{
"<属性名>":"<属性值>"
}
}
}
"constant_score":{
"filter":{
"match":{
"<属性名>":"<属性值>"
}
},
"boost":2
}
}
}