ELK02-ElasticSearch熟悉

 

ElasticSearch的基本组件:

索引(Index): 文档容器,索引是具有类似属性的文档的集合。类似于关系型的表,索引名不需使用小写字符。

类型(type): 类型是索引内部的逻辑分区,其意义完全取决于用户需求。一个索引内部可定义一个或多个类型,相当于关系型表结构

文档(document): 文档是Lucence索引和搜索的原子单位,它包含了一个或多个域。是域的容器;基于JSON格式表示。每个域的组成部分: 一个名字,一个或多个值;拥有多个值的域,通常称为多值域。

映射(mapping): 原始内容存储为文档之前需要事先进行分析(分词);映射用于定义此分析机制该如何实现,分析包括切词、过滤等。此外,ES还为了mapping提供了其他功能,例如:域中内容排序等。

ElasticSearch的集群组件:

Cluster: ES的集群标识为进群名称,默认为elasticsearch。节点就是靠此名字决定加入那个集群中(一个节点只能属于一个集群)

Node:运行了单个ES实例的主机即为节点。用于存储数据、参与集群索引及搜索操作。节点的标识依赖节点名,节点ID默认会随机生成

Shard: 将索引切割成为的物理存储组件,每个Shard都是一个完整的、独立的索引。创建索引时,ES默认将其分割为5个shard,用户也可以按需自定义。

Shard分为两种类型:primary shard 和 replica(primary shard的副本)

primary shard:
每个索引对ES讲都会被切成5个primary shard,按理每个primary都应该有 replica
但是可以为多个,每个索引创建后shard不能更改
replica:
Replica可以用于冗余,也可以作为读的负载均衡
副本可以动态修改数量

ElasticSearch集群的工作过程:

启动时,通过多播(默认)或单播方式在9300/tcp查找同一集群中的其他节点,并与之建利通讯。
集群中的所有节点会选举出一个主节点负责管理整个集群状态,以及在集群范围内决定各shards的分布方式,站在用户角度而言每个节点都可以响应用户所有请求,用户无需确认哪个是主节点。
必要时如果有节点宕机,主节点会根据集群状态修复,并确认所有可用的shards和主shards。
集群状态:green(正常),red(不可用),yellow(修复)。
在yellow状态下所有shard都属于未分配shard,副本不可用,只能使用主的;如果宕机的是主shard则replica称为主shard。
yellow状态下吞吐能力有限,如果某个shard副本少于配额,会自动补充。
周期性检查各节点的健康状态,修复后rebalance各节点。
如果primary shard宕机,而有多个replica,由选举过程决定谁成为primary shard。

当然也可以手动指定Master节点,就像我们部署的那样。

ElasticSearch提供了一个Restful风格的API

ES API的类型:
1、检查集群、节点、索引等健康与否,以及获取其相应状态。
2、管理集群、节点、索引及元数据。
3、执行CRUD操作(增删查改)。
4、执行高级操作,例如paging,filtering等。

格式:

curl -X<http_action(get/put/post/delete)> 'http(s)://HOST:PORT/<PATH>?<QUERY_STRING>' -d '<BODY>' 
QUERY_STRING: 查询参数,例如?pretty表示易读的json格式输出
BODY: 请求的主题

curl -X GET '192.168.2.130:9200/?pretty' #查看单个节点的信息,由于curl方式默认就是GET 所以可以写成curl 192.168.2.130:9200/?pretty 

cat 查看集群API,API都用_xxx的方式表示,下划线

curl -X GET 'http://192.168.2.130:9200/_cat' #列出所有cat方法

curl -X GET 'http://192.168.2.130:9200/_cat/nodes?v'  #查看节点信息,?v 代表详细格式(可不加)

curl -X GET 'http://192.168.2.130:9200/_cat/nodes?help' #获取node可查询相关帮助

curl -X GET 'http://192.168.2.130:9200/_cat/nodes?h=name,ip,port,uptime,heap.current' #查询节点部分信息,关键字可以在上行帮助里找到

curl -X GET 'http://192.168.2.131:9200/_cat/master?v' #查看主节点信息,可以从其他节点查询

curl -X GET 'http://192.168.2.130:9200/_cat/health?v' #查看集群健康状态

如果不方便登入ES主机操作,也可以登入Kibana或者ElasticHQ进行操作

集群  APIs  _cluster

curl -X GET 'http://192.168.2.130:9200/_cluster/health?pretty'   #获取集群健康信息

curl -X GET 'http://192.168.2.130:9200/_cluster/health/nginx-test-2019.10.14,nginx-test-2019.10.16'  #获取索引健康信息

curl -X GET 'http://192.168.2.130:9200/_cluster/health?level=shards&pretty'  #查看索引shard信息

CURD(增删查改)索引管理 APIs

-H "Content-Type: application/json" -- 由于新版本的ElasticSearch新增了安全机制,不加肯能会报错,出现 "

"error" : "Content-Type header [application/x-www-form-urlencoded] is not supported",
"status" : 406

"的报错,当然以前的版本也需要只不过以前不强求用户要加入此header头。

Why are we changing this?

We know that the content-type sniffing has been quite convenient when using basic HTTP tools such as curl. Many of us are quite accustomed to searching a cluster by running something like this:

curl 'http://localhost:9200/_search' -d'
{
    "query" : {
        "match_all" : {}
    }
}'
知识兔

But, we need to make that sort of operation slightly more verbose, and include the content-type, in the interests of clarity and security.

新增文档,payroll的索引和devops的类型会自动创建

curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/1?pretty' -d '{
"name": "Alice",
"sex": "F",
"job": "UI",
"salary": "10000",
"performance": "2000",
"tax": "-1900",
"payment": "10100"
}'

curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/2?pretty' -d '{
"name": "Tom",
"sex": "M",
"job": "UI",
"salary": "10000",
"performance": "2000",
"tax": "-1900",
"payment": "10100"
}'

curl -H "Content-Type: application/json" -XPUT '192.168.2.130:9200/payroll/devops/3?pretty' -d '{
"name": "Gaemon",
"sex": "F",
"job": "UI Manager",
"salary": "18000",
"performance": "5000",
"tax": "3200",
"payment": "19800"
}'

获取文档信息

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/2?pretty'

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/3?pretty'

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/_search?q="Alice"'   #查询某个域与条件匹配的数据

更新文档,ES中更新文档有两种方式:

1、使用PUT直接覆盖,相同的index、type和id 就会覆盖替换

2、_update APIs 

curl -H "Content-Type: application/json" -XPOST '192.168.2.130:9200/payroll/devops/1/_update?pretty' -d '
{
"doc": { "job": "JAVA" }
}'
{

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/devops/1?pretty'

{
"_index" : "payroll",
"_type" : "devops",
"_id" : "1",
"_version" : 3,
"_seq_no" : 4,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Alice",
"sex" : "F",
"job" : "JAVA",
"salary" : "10000",
"performance" : "2000",
"tax" : "-1900",
"payment" : "10100"
}
}

删除文档

curl -H "Content-Type: application/json" -XDELETE '192.168.2.130:9200/payroll/devops/1'

删除索引

curl -H "Content-Type: application/json" -X GET '192.168.2.130:9200/_cat/indices?v'   #先查询现有文档

curl -H "Content-Type: application/json" -XDELETE '192.168.2.130:9200/nginx-test-2019.10.14'

查询数据,采用域查询语言(Query DSL)基于json

可以实现诸多类型的查询操作,比如simple term query, range,boolean,fuzzy等,可以逻辑组合查询。

ES的查询分为两个阶段:

分散到shard所在节点-如果被查询的shard不在本地,需要转发查询。

合并所有shard返回的结果。

查询方式也有两种:

1、通过Restfull request API查询,也称为query string
  #查询索引所有文档
  curl -XGET 'localhost:9200/students/_search?pretty'
  #hits 为命中的文档,里面的id为文档id

2、通过发送REST request body 进行
  #query body 可以更为详细的写查询
  curl -XGET 'localhost:9200/students/_search?pretty' -d '
  {
  "query": { "match_all": {} }
  }' #mathc_all 查询所有

多索引、多类型查询

查询所有索引
curl -XGET '192.168.2.130:9200/_search?pretty'
多索引查询
curl -XGET '192.168.2.130:9200/INDEX1,INDEX2,INDEX3/_search?pretty'
使用通配符多索引查询,s开头和t开头的索引
curl -XGET '192.168.2.130:9200/d*,n*/_search?pretty'
多类型查询
curl -XGET '192.168.2.130:9200/payroll/devops,hr/_search?pretty'    #如果有hr这个类型

Mapping和Analysis:

ES对每一个文档会取得其所有域的所有值,生成一个名为"_all"的域;执行查询时,如果query_string未指定域,则在_all域上执行查询操作。

全域搜索 (_al)

curl -H "Content Type: application/json" -XGET '192.168.2.130:9200/_search?q='10000''  #查询所有域中与条件相等的值,并列出此文档全部数据

#如果涉及到空格,可以用%20来代替

指定域搜索,做精确匹配

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/_search?q=job:"UI"'  #只对job做查询,当然他也属于模糊查询,job中有UI的都会查出来

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/_search?q=job:"UI%20Manager"'   #空格用%20代替,如果不行则复制到浏览器中使用空格表示,浏览器会自动转换

查询index中的doc字段信息

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_mapping?pretty'

ES中搜索的数据广义上可被理解为两类:
1、types:exact #指定类型上做精确搜索
  精确值:指未经加工的原始值,精确匹配

2、full-text
  全文搜索时用于引用文本中的数据,不区分大小写,可能还有近义词,模糊匹配,查询相关度
  为了完成full-text搜索,ES必须先分析文本,并创建倒排索引,还需要进行"正规化"标准格式,多为小写、近义词替换修改
    分析(分析器) analyzer
      分词
      正规化
      构建倒排索引

  分析器三个组件构成:
    字符过滤器 (过滤、不需要分词字符、html标签等)
    分词器
    分词过滤器 (过滤助词)

  ES内置的分析器:
    standard analyzer #ES默认的,根据Unicode标准进行分词,中文也是可以的
    simple analyzer#简单分析器,非字母作为单词边境
    whitespace analyzer #空白字符分析器,空白最为单词边境
    Language analyzer #语言分析器,适用于多语言的

  分析器不仅是创建索引是用到;在构建查询时也会用到
    对查询 去除html标签、切词、正规化

  搜索和查询时要选择保证结果一致的分析器

ES Query DSL 深入

  request body:
    分成两类:
      query dsl
        需要根据查询条件的相关度选择query_dsl,执行full-text查询时评判匹配程度
        查询过程复杂,不能缓存结果
      filter dsl
        精确值查询,匹配或不匹配,执行exact查询时,基于结果"yes"或"no"评判
        执行速度块快,适用于缓存,结果可缓存

   查询语句结构:
  {
  Query_name:{
  ARGUMENT: VALUE,
  ARGUMENT: VALUE,
  ...
  }

  {
  Query_name:{
  FIELD_NAME:{
  ARGUMENT: VALUE
  }
   }

filter dsl:

term filter:

精确匹配包含指定项的文档

UI Manager #UI可以视为一项,Manager也可以视为一项,UI%20Manager也是一项

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"term": {"job": "UI"}
}
}'

你会发现当你在匹配UI时结果为空,这是因为标准分词器,是将字段内容以小写方式记录,并倒排索引,term精确匹配是区分大小写的。

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"term": {"job": "ui"}
}
}'

现在得到了你想要的结果。

查询全部内容

curl -H "Content-Type: application/json" -XGET "192.168.2.130:9200/payroll/_search?pretty" -d'
{
"query":
{
"match_all":{}
}
}'

多项精确匹配

curl -H "Content-Type: application/json" -XGET '192.16 8.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"terms": { "name": ["alice","tom"] }
}
}'

范围精确查询,当初salary值给的是字符格式,不是数值所以无法比较,这个只是示例

curl -H "Content-Type: application/json" -XGET '192.168.2.130:9200/payroll/_search?pretty' -d'
{
"query": {
"range": {"salary": "gte":8000,"lte":25000}
}
}'

判断是否存在

exists and missing filters:
{ "exists": {
"Age": 25
}
}

布鲁尔值判断

boolean filter:
基于boolean的逻辑来合并多个filter子句:
must: 其内部所有的子句条件必须同时匹配,and关系
must:{
"term": { "age": 25 }
"term": { "gender": "Female"}
}

must_not: 其所有子句必须不匹配。not条件
must_not:{
"term": { "age": 25 }
}

should: 至少有一个子句匹配 ,or 关系
should:{
"term": { "age": 25 }
"term": { "gender": "Female"}
}

full-text、exact-value查询

match_all Query:
用于匹配所有文档,没有指定任何query,默认即为match_all
{ "match_all": {} }

match Query:
几乎在任何域上执行full-text或exact-value查询
如果执行full-text查询: 首先对查询时的语句做分析:
{ "match": {"students": "Guo"} }
如果执行exact-value查询:搜索精确值,此时,建议使用过滤,而非查询
{ "match": {"name": "Guo"} }

multi_match Query:
用于在多个域上执行相同的查询:
{
"multi_match":
"query": full-text search
"field": {'field1','field2'}
}

{
"multi_match":
"query": {
"students": "Guo"
}
"field": {
"name",
"description"
}
}

可以合并filter和query一起使用
组合查询
{
"filterd": {
query: { "match": {"gender": "Female"} }
filter: { "term": {"age":25} }
}
}

查询语句语法检查:
返回对错
GET /$index/_validate/query?pretty
{
$query_body
}

返回错误详情
GET /$index/_validate/query?explain&pretty
{
$query_body
}

计算机