探索ES-什么?你还不知道ES?(一)

前文回顾

以前有讲过碎碎念-探索计划(九),并且也陆续发了9篇关于Spring Boot的探索系列(固然远远尚未结束)。一个是由于碎碎念-以终为始(四)中提到,个人其中一条目标是可以作出一个有价值的产品,因此探索计划也要扩展一名对将来可以作出一个产品有帮助的新成员ES了。另一个就是公司也使用到了ES,因此要加快输入和输出的脚步了。今天就来带你从小白到入门EShtml

介绍

ES是一个搜索引擎,底层基于LucceeElasticSearch刚开始是由于在伦敦的一个程序员要给老婆搜索菜谱才开发出来的。东西被创造出来都是由需求驱动的,而后最后这个东西存在的意义是否仍是最初的需求就不必定了。java

环境

eskibana都是5.0.2版本,起码今天是这个版本的。不过以后可能考虑升级到6.7版本。node

安装步骤

单节点部署

  1. 下载es和kibana的安装包,解压
  2. 修改配置文件 elasticsearch.yml
  • cluster.name:my-application(当前集群名称)
  • node.name:node-1(当前节点名称)
  • network.host:localhost(最好修改成本机IP地址,在集群环境下localhost可能会有问题)
  • http.port:9200(ES端口)

集群部署配置

  • discovery.zen.ping.unicast.host:["host1","host2"] (其余节点的IP地址和本身节点的地址)
  • dicovery.zen.minimum_master_nodes:(node_numbers / 2) + 1

修改JVM内存大小

  1. 修改jvm.options中内存大小 (考虑到性能不要设置太大,要为os cache预留一部份内存,保证磁盘上面的数据大小和os cache的大小是一致的,不懂没有关系,后来慢慢讲解)

启动

  1. 启动 bin/elasticsearch -d (-d表示用守护模式打开)
  2. 访问查看ES状态 curl http://localhost:9200 (有些状况下不能使用localhost,而是必须使用ip;看绑定的地址是什么,若是显示指定了IP,那么必须是IP) 能够返回结果
{
  "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安装

虽然能够不安装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

查看ES状态所有索引

查看索引的存在状态bash

GET _cat/indices?v&pretty
复制代码

查看ES节点配置信息

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
}
复制代码

基本概念

Node

节点。每一个ES实例都是一个节点。能够对每一个启动的ES节点设置一个惟一的节点名称,在elasticsearch.ymlnode.name字段来指定。在ES中节点存在不一样的类型,首先数据节点是存储数据的。每次一个请求进来,由于每个节点都拥有协调能力,在请求进来的时候,节点自动成为协调节点。

另外还有master节点和数据节点。master节点存储了ES集群的元信息。当请求进入到master节点时,master节点根据hash算法和分片信息,将请求打入到对应的分片上面。

Cluster

集群。多个ES节点能够组成一个集群。只要节点的集群名字相同便可。在elasticsearch.ymlcluster.name来指定。只要cluster.name相同,那么在节点之间网络连通的状况下,多个节点会自动组成一个集群。

Index

index就是ES的索引,简单理解为Mysql的数据库。一个ES节点能够有多个索引。

Type

索引的类型。简单理解为Mysql的表。对一个索引进行逻辑上面的区分。一个索引下面能够有多个type。

Document

文档。至关于数据库里面的记录。一个type下面能够多个文档。

Shards And Replicas

分片和副本。一个索引默认会有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%
复制代码
  • docs.count:表示该索引下面全部的文档数

插入ES操做

有了索引以后,可使用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查询

那么如今测试数据都进入了ES,如何查询呢?通常人可能会有两种查询需求,一种是查询某个索引下面全部的数据,一种是根据id来查询,另外就是根据某一个具体的字段来查询。一个一个来看。 首先全部的查询都必须加上_search字段在请求的末尾。

  • 查询索引下面所有的文档。只要在须要查询的index后面加上_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的文档。这里的含有就是指定的字段必须是全文索引的。 可是想要精确地搜索nameJohn的文档。就可使用term查询,而不是match查询。

POST _search
{
  "query": {
    "term" : { "name" : "John" } 
  }
}
复制代码

ES更新文档

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。

相关文章
相关标签/搜索