以前有讲过碎碎念-探索计划(九),并且也陆续发了9篇关于Spring Boot
的探索系列(固然远远尚未结束)。一个是由于碎碎念-以终为始(四)中提到,个人其中一条目标是可以作出一个有价值的产品,因此探索计划
也要扩展一名对将来可以作出一个产品有帮助的新成员ES
了。另一个就是公司也使用到了ES
,因此要加快输入和输出的脚步了。今天就来带你从小白到入门ES。html
ES是一个搜索引擎,底层基于Luccee
。ElasticSearch
刚开始是由于在伦敦的一个程序员要给老婆搜索菜谱才开发出来的。东西被创造出来都是由需求驱动的,而后最后这个东西存在的意义是否仍是最初的需求就不必定了。java
es
和kibana
都是5.0.2版本,起码今天是这个版本的。不过以后可能考虑升级到6.7版本。node
elasticsearch.yml
jvm.options
中内存大小 (考虑到性能不要设置太大,要为os cache预留一部份内存,保证磁盘上面的数据大小和os cache的大小是一致的,不懂没有关系,后来慢慢讲解){
"name" : "node-1",
"cluster_name" : "my-application",
"cluster_uuid" : "0P_LVzBYS6qVl8Wo9o817Q",
"version" : {
"number" : "5.0.2",
"build_hash" : "f6b4951",
"build_date" : "2016-11-24T10:07:18.101Z",
"build_snapshot" : false,
"lucene_version" : "6.2.1"
},
"tagline" : "You Know, for Search"
}
复制代码
虽然能够不安装Kibana,可是通常安转完ElasticSearch都会安装Kibana。(以后讲解详细安装kibana详细步骤)程序员
安装完ES以后,通常人确定会想要知道一些ES的状态基本信息,就好像安装完数据库以后,就想要知道这个数据库安装在哪一个ip地址,里面有多少张表,表占用了多少空间等等基本信息。那么对于ES来讲就是下面几点。算法
查看健康状态实际上是和ES分片有没有被分配有关系。存在主分片没有被分配是Red。主分片已经被分配,可是副本分片没有被分配是Yellow。刚开始学习最多见的Yellow状况就是ES只启动了一个节点,副本分片不能和主分片在同一个节点上,致使副本分片没法被分配。 主分片和副本分片都分配的状况下,集群才是Green。sql
GET _cat/health?v&pretty
复制代码
看完了集群的健康状态以后,能够查看每个节点的详细信息,内存使用状况,cpu的使用状况等数据库
GET /_cat/nodes?v
复制代码
参考 cat-nodesjson
查看索引的存在状态bash
GET _cat/indices?v&pretty
复制代码
GET _nodes?pretty
复制代码
能够查看某个特定索引的分片状况,状态、在哪一个节点等网络
GET _cat/shards/indexName*?pretty&v
复制代码
通常默认的好像不全面,可使用下面这个语句。
GET _cat/shards?h=index,shard,prirep,state,unassigned.*&pretty&v
复制代码
经过这个语句能够看到分片级别的状态,我发现ES有些API也不是很好。indices这个API都没有说明没有分片的个数。可是health里面又存在整个集群下没有分片的个数。
GET /_cluster/allocation/explain
{
"index":"bank",
"shard":0,
"primary":false
}
复制代码
节点。每一个ES实例都是一个节点。能够对每一个启动的ES节点设置一个惟一的节点名称,在elasticsearch.yml
的node.name
字段来指定。在ES中节点存在不一样的类型,首先数据节点是存储数据的。每次一个请求进来,由于每个节点都拥有协调能力,在请求进来的时候,节点自动成为协调节点。
另外还有master节点和数据节点。master节点存储了ES集群的元信息。当请求进入到master节点时,master节点根据hash算法和分片信息,将请求打入到对应的分片上面。
集群。多个ES节点能够组成一个集群。只要节点的集群名字相同便可。在elasticsearch.yml
的cluster.name
来指定。只要cluster.name
相同,那么在节点之间网络连通的状况下,多个节点会自动组成一个集群。
index
就是ES的索引,简单理解为Mysql的数据库。一个ES节点能够有多个索引。
索引的类型。简单理解为Mysql的表。对一个索引进行逻辑上面的区分。一个索引下面能够有多个type。
文档。至关于数据库里面的记录。一个type下面能够多个文档。
分片和副本。一个索引默认会有5个分片和1个备份,会产生5个主分片和5个备份分片。5个分片会分散到集群中不一样的节点上面,另外须要注意的是主分片和副本分片必定不能再同一个节点上。若是有多个副本分片,相同数据的副本分片也不能在同一个节点上面。否则会致使分片没有被分配。
Replica是ES实现高可用的一种方式,以后会进行深刻的扩展。
也可能会遇到一些问题?好比ES没有分配分片?以后会有文章会讲到故障的排查。
跟数据库同样,要使用数据库首先要建库,在ES里面就是创建索引。索引index
至关于数据库,type
至关于表,id
至关于文档的主键。
PUT /people?pretty
复制代码
而后可使用查询所有索引的语句查看,能够发现多了一条记录。
ES与关系型数据库不一样的地方在于ES是能够动态增长字段的。 因此,建索引(建表)的时候能够不指定全部的字段,当有新的字段存在时,可使用动态映射的方式(dymatic mapping)来指定字段类型。
要注意的点是一个新的字段是什么类型只有在第一次这个字段进去到ES时会被指定,其余时候不会被指定。
查看节点状态可以看到只是yellow
,由于当前只有一个节点,副本分片不能和主分片在同一个节点上,致使副本分片没有被分配,没有实现高可用。
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1554208915 20:41:55 my-application yellow 1 1 6 6 0 0 6 0 - 50.0%
复制代码
有了索引以后,可使用Restful接口插入数据到ES中。使用下面的语句创建。
PUT /people/info/1?pretty
{
"name": "John Doe"
}
复制代码
这里的1就是建立的新文档的id,能够指定也能够不指定。建议不指定,会快一些。成功以后提示以下。
{
"_index": "people",
"_type": "info",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
复制代码
这里使用的是PUT
指令,表示更新指定的文档。由于是更新指定的文档,因此这里第三个参数1
是必须填写的。ES的更新文档的操做实际上是会判断文档存不存在,若是不存在那么就是新建一条新的文档。若是想要直接真正新建一条文档,并且这种状况下也不须要填写id,能够直接新增,可使用POST
方式,以下。
POST /people/info?pretty
{
"name": "John Doe"
}
复制代码
返回格式以下。
{
"_index": "people",
"_type": "info",
"_id": "AWnjMpZuDCZ3hLyrI_RF",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}
复制代码
还可使用bulk来批量插入数据,以下所示。要注意的是bulk对于json的格式有严格的要求,每个完整的json只能是一行,不能多行。而已一个完整json以后必须换行。
bulk还能够这样写
POST /customer/external/_bulk?pretty
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
复制代码
那么如今测试数据都进入了ES,如何查询呢?通常人可能会有两种查询需求,一种是查询某个索引下面全部的数据,一种是根据id来查询,另外就是根据某一个具体的字段来查询。一个一个来看。 首先全部的查询都必须加上_search
字段在请求的末尾。
_search
就行了。GET /people/_search
复制代码
也能够这样写。
GET /people/_search
{
"query": { "match_all": {} }
}
复制代码
返回以下。
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 1,
"hits": [
{
"_index": "people",
"_type": "info",
"_id": "AWnjMpZuDCZ3hLyrI_RF",
"_score": 1,
"_source": {
"name": "John Doe"
}
},
.....省略后面5条数据
复制代码
match
查询。GET /people/_search
{
"query": {
"match": {
"name": "John"
}
}
}
复制代码
这里就是搜索全部name中含有John的文档。这里的含有就是指定的字段必须是全文索引的。 可是想要精确地搜索name
是John
的文档。就可使用term
查询,而不是match
查询。
POST _search
{
"query": {
"term" : { "name" : "John" }
}
}
复制代码
PUT /people/info/1?pretty
{
"name": "John Doe"
}
复制代码
经过上面这个更新的语句就能够将文档更新。可是这里重点要讲一下,这个更新操做是覆盖更新。在ES的底层,更新操做会先找到这条ES数据,而后用新的ES数据给彻底覆盖掉这条数据。
可是每每有时候咱们想要实现的是增量更新,那么应该怎么办呢?
PUT /people/info/1/_update
{
"doc":{
"name":"Mike"
}
}
复制代码
经过这种方式就能够将某一个文档增量更新了。可是若是要删除某一个文档里面的一个字段,应该只能用全量的方式了吧。注意这里的语法必定要加上doc,url上面要加上_update。
GET _search
{
"query": {
"match_all": {}
}
}
复制代码
全部的命令能够总结为
<REST Verb> /<Index>/<Type>/<ID>
POST /_search
{
"query" : {
"term" : { "product" : "chocolate" }
},
"sort" : [
{"price" : {"order" : "asc"}}
]
}
复制代码
ES不只提供了数据的搜索还提供了数据的检索,聚合。下面就来聊一聊聚合操做。
先来个简单的聚合操做。 首先下载app.json
的原始数据。需求是按state
来分组计算出分组中document
的数量,而后计算分组内金额的平均数。size:0
表示不会返回命中的document
,只是返回分组,在ES中分组又被称之为桶bucket
,默认返回10个桶。
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
},
"aggs": {
"average_balance77": {
"avg": {
"field": "balance"
}
}
}
}
}
}
复制代码
获得以下结果
{
"took": 75,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1000,
"max_score": 0,
"hits": []//size:0,所示hits不展现
},
"aggregations": {
"group_by_state": {
"doc_count_error_upper_bound": 20,
"sum_other_doc_count": 770,
"buckets": [//第一个bucket
{
"key": "ID",
"doc_count": 27,
"average_balance77": {//balance平均数
"value": 24368.777777777777
}
},
{//第二个bucket
"key": "TX",
"doc_count": 27,
"average_balance77": {//balance平均数
"value": 27462.925925925927
}
},
复制代码
看过简单的聚合以后,是否是火烧眉毛想要看看复杂的聚合操做呢?先上例子。
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_age": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 30
},
{
"from": 30,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field": "gender.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
}
复制代码
其实就是聚合以后能够再次对于已经聚合以后的数据进行聚合操做。就好像sql中group by
以后,再对group by
以后的数据再次进行group by
操做。分桶以后能够再次分桶。
好了,看完了上文,关于ES的安装、部署、查询、更新、聚合等基本操做都掌握了吗?
之后这里天天都会写一篇文章,题材不限,内容不限,字数不限。尽可能把本身天天的思考都放入其中。
若是这篇文章给你带来了一些帮助,能够动动手指点个赞,顺便关注一波就更好了。
若是上面都没有,那么写下读完以后最想说的话?有效的反馈和你的鼓励是对我最大的帮助。
另外打算把博客给从新捡起来了。欢迎你们来访问吃西瓜。
我是shane。今天是2019年8月16日。百天写做计划的第二十三天,23/100。