ElasticSearch

# ElasticSearch学习文档

## 核心概念

ES属于面向文档型的数据库:索引>>数据库、类型>>表、文档>>行、字段>>列,由于使用了*倒排索引*的概念,则类型(Type)的概念被弱化。

倒排索引:通过文档内容关联文档id。

映射:表示索引的数据结构信息

分片:类似分表,由于单索引数据量巨大,使用时受限于单节点的硬件性能,同时从多个节点的分片中读取索引数据时性能将会提高。

副本:为防止节点数据丢失,在其他节点建立分片的副本。副本将会同步主分片的数据。

## 映射相关

text:text类型的字段会默认被分词,如果存入一个text类型字段某个值时,值的本身将不存在于倒排索引中。例如存入content字段“hello world”,则倒排索引中只会存在hello和world,此时通过term查询“hello world”查询不到文档。在es5版本之后,如果一个字段被定义为text类型,则将会默认为其生成content.keyword字段,类型为keyword,不进行分词,默认保留256个字符直接放入倒排索引中。解决了上述问题。考虑到仅保存256个字符,如果存在content字段存在大量文本,则需手动建立content.keyword设置其 not_analyzed

keyword:存入类型为keyword的字段的值将不会被分词。

## 分词相关

在插入字段时,分词器将会对值进行分词,将分词结果保存到倒排索引中。

english analyzer会将词还原为原始形态,例如learning>learn,courses>course。

ik:中文分词器。分为ik_max_word(常用,细粒度)和ik_smart(不常用,粗粒度)。

配置文件:${es_root}/plugins/${ik_root}/config 下:

IKAnalyzer.cfg.xml:用来配置自定义词库

main.dic:原生词库。

stopword.dic:英文停用词。 不能 

## filter查询原理

1. 在倒排索引中查找搜索串,获取document list
2. 使用找到的doc list,构建bitset,就是一个二进制数组,用来标识一个doc对filter是否匹配。[0,1,0,1,0,0]
3. 遍历每个过滤条件对应的bitset(每个filter都会构建bitset),优先从最稀疏(数组中0最多的)的开始搜索,先过滤掉尽可能多的数据,查找满足所有条件的doc返回给client。
4. caching bitset,跟踪filter,在最近的256个filter中,某个filter超出一定次数将会缓存其对应的bitset。对于小segment(<1000或<3%),不缓存。filter相比与query的好处就在于会caching。
5. filter大部分情况下会在query前执行,先尽量过滤掉尽可能多的数据。query会计算doc对搜索条件的相关度,还根据score排序。
6. 如果document有新增或者修改时,cached bitset会被自动更新。
7. 以后只要有相同条件的filter,将会直接使用对应的bitset。

## 查询相关

1. bool:bool内可以与must,must_not,should组合过滤,同时三个子对象可以嵌套bool。

2. 当should和must同时使用时,should中的条件可以都不满足,仅影响相关分数;但当should单独使用时,必须满足其中一个条件才可以。可以同"minimum_should_match"搭配使用。

3. term :对搜索文本不分词,直接拿去倒排索引中匹配。对数字、bool、date天然支持

4. terms:如果字段类型类似数组形式时,使用terms来匹配数组内的任意元素。

   ```json
   "terms":{"tags":["ydsmp"]}
   //使用term及terms查询时,一定要注意查询条件是否在倒排索引中存在。例如: 
   "tags":[ "app=ydsmp", "ip=10.127.25.155","host=ydsmp-hu2kukd"]
   //此文档的分词结果为【app,ydsmp,ip,10.127.25.155,host,hu2kukd】,此时如果使用
   "terms":["tags":["app=ydsmp"]]
   //将不会有任何结果。
   ```

5. filter:filter内可以与bool,range组合过滤(同一级别只能使用一个?),支持嵌套。不计算相关分数

6. match:匹配查询,查询条件将会被分词。精确度低。例:

```json
{
    "match":{
        "$field":"$value"
    }
}  
//或
{
    "match":{
    "$field":{
        "query":"$value",
        "operator":"or",
        "minimum_should_match":"75%(最少应满足)"
    }
}
}
```

​            在使用match匹配时,es会在底层将match转换为bool、should/must、term转换,例:

```json
{
    "match":{
        "title":{
            "query":"java go",
            "operator":"or",
            "minimum_should_match":"50%"
        }
    }
}
//转换为
{
    "bool":{
        "should":[
            {
                "term":{
                    "title":"java"
                }
            },
            {
                "term":{
                    "title":"go"
                }
            }
        ],
        "mimimum_should_match":1
    }
}
```

7. ​    boost:权重。可以将某个搜索条件的权重加大,计算score时会更高,默认为1。
8. dis_max:为*Disjunction Max Query* ,分离最大化查询指的是,将任何与任一查询匹配的文档作为返回结果,但只将最佳匹配的评分作为查询的评分结果返回。通过使用*tie_breaker*选项,也会考虑其他匹配的评分乘以参数***0.2***计算进去。

```json
{
    "query":{
        "dis_max":{
            "queries":[
                {
                    "match":{}
                },
                {
                    "match":{}
                }
            ],
            "tie_breaker":0.2
        }
    }
}
```

9. multi_match:基于dis_max、match(minimum_should_match、boost)、tie_breaker整合的匹配命令。转换关系如下:

```json
{
    "query":{
        "multi_match":{
            "query":"java solution",
            "type":"best_fields",
            "fields":["title^2","content"],
            "tie_breaker":0.3,
            "minimum_should_match":"50%"
        }
    }
}
//转换为
{
    "query":{
        "dis_max":{
            "queries":[
                {
                    "match":{
                        "title":{
                            "query":"java solution",
                            "minimum_should_match":"50%",
                            "boost":2
                        }
                    }
                },
                {
                    "match":{
                        "content":{
                            "query":"java solution",
                            "minimum_should_match":"50%"
                        }
                    }
                }
            ],
            "tie_breaker":0.3
        }
    }
}
```

10. best_fields与most_fields策略
11. match_phrase:匹配短语。召回率低。由于要计算分词的position和slop,所以性能比单纯的match低很多。

```json
//省略上级
{
    "match_phrase":{
        "title":"java spark"
    }
}
// 首先,match_phrase的条件仍然是分词的,将查询条件java spark分词为【java、spark】
// 然后,用term分别匹配两个词,即 
{
    "must":[
        {
            "term":{"title":"java"}
        },
        {
            "term":{"title":"spark"}
        }
    ]
}
// 最后,判断过滤出的文档中的title值,在倒排索引中,spark.position刚好比java.position大1的,即为满足查询条件。
```

12. 使用match_phrase+slop做近似匹配。 slop的值表示分词的偏移量。
13. 混合使用match是match_phrase+slop做召回率(通过match)和精确度(通过match_phrase+slop)的平衡。

```json
{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{// 过滤出满足条件的doc
                        
                        "title":{
                            "query":"java spark"
                        }
                    }
                }
            ],
            "should":[
                {
                    "match_phrase":{// 在slop以内,匹配的文档如果 java和spark靠的越近,则获得的分数越高,排序将越靠前
                        // 针对大量文档,如果通通计算其position和slop时,将会耗费时间过长,可通过rescore选项来提高效率,具体baidu
                        "title":{
                            "query":"java spark",
                            "slop":50
                        }
                    }
                }
            ]
        }
    }
}
```

## 模糊查询

1. prefix:用户同match,前缀搜索。前缀搜索不计算相关分数,即query.prefix同filter.prefix的唯一区别就是filter会cache bitset。prefix会扫描全部的倒排索引,性能差。

```json
{
    "query":{
        "prefix":{
            "title":{
                "value":"C3"
            }
        }
    }
}
```

2. wildcard:通配符搜索。需扫描全部倒排索引,性能差。

```json
{
    "query":{
        "wildcard":{
            "title":{
                "value":"*5?5"
            }// * 表示任意多个字符;? 表示一个字符
        }
    }
}
```

3. regexp:正则表达式。同上。

```json
{
    "query":{
        "regexp":{
            "title":"C[0-9].+"
        }
    }
}
```

4. match_phrase_prefix:搜索推荐。

```json
{  // 将条件分词为 hello w,先根据hello,match_phrase出docs1, 然后根据w做 prefix前缀搜索,过滤出docs2,取交集
    // 再通过slop去计算 hello和w 的匹配度
    "match_phrase_prefix":{
        "title":{
            "query":"hello w",
            "slop":10,
            "max_expansions":50 //指定prefix在倒排索引中最多匹配到50个文档后,不继续匹配,提高性能。
        }
    }
}
```

5. ngram模型:百度。使用edge ngram进一步分词增加倒排索引容量,此时在实现搜索推荐功能时,使用match即可。
6. fuzzy:自动将拼写错误的搜索文本自动纠正,纠正后尝试匹配倒排索引。

```json
{
    "query":{
        "fuzzy":{
            "title":{
                "value":"hallo",
                "fuzziness":2  // 指的是搜索文本最多纠正几个字符来匹配,默认2
            }
        }
    }
}
```

## 聚合基础

两个核心概念:bucket和metric

bucket:一个数据分组,例如基于某个字段分组,字段值相同的文档将会被划分到一个bucket中。

metric:对一个分组内的数据进行某种统计。比如计数,取和,最大值等。

1. 统计每个应用的SQL执行时间平均值,并降序排序

```json
{
  "size": 0,
  "query": { //过滤掉错误数据, 下面的聚合操作需要在此Scope下执行
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        }
      ]
    }
  },
  "aggs": {
    "app_group": {// 分组的名称
      "terms": {
        "field": "APP.keyword", // 根据此字段分组,分成多个bucket
          "order": {
          "avg_time": "desc"  //按照aggs.name为avg_time的metric降序
        }
      },
      "aggs": { // 对上面每个bucket执行运算(metric)
        "avg_time": {
          "avg": { //
            "field": "costTime" // 对costTime字段进行平均值计算
          }
        },
         "max_time":{
             "max":{
                 "field":"costTime"
             }
         }
      }
    }
  }
}
```

2. 统计每个应用的各个服务的SQL执行时间平均值。执行两次分组,在1中APP进行分组完毕后,再次进行服务的分组,最后计算metric。

```json
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        }
      ]
    }
  },
  "aggs": {
    "app_group": {
      "terms": {
        "field": "APP.keyword"
      },
      "aggs": {
        "avg_time": {
          "avg": {
            "field": "costTime"
          }
        },
        "service_group": {  //以下为下钻内容。 一个aggs.name下可以同时包含多个metric或一个bucket(见1)。一个aggs可以包含多个aggName(见6)
          "terms": {
            "field": "eventCode.keyword"
          },
          "aggs": {
            "avg_time": {
              "avg": {
                "field": "costTime"
              }
            }
          }
        }
      }
    }
  }
}
```

3. 计算执行时间在某个时间段内的平均值。引入histogram:类似于terms,也是进行bucket分组操作,会接收一个field,按照字段值的各个范围区间进行分组操作。

```json
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        }
      ]
    }
  },
  "aggs": {
    "timeRange": {
      "histogram": {
        "field": "costTime", // 通过costTime字段划分
        "interval": 100   // 划分方式0-100,100-200,200-300等
      },
      "aggs": {// 子聚合
        "app_group": {
          "terms": {// 通过APP分组
            "field": "APP.keyword"
          },
          "aggs": {
            "avg_time": {
              "avg": { // 计算各个APP在0-100区间内的平均值(属于下钻)
                "field": "costTime"
              }
            }
          }
        },
        "avg_time": {
          "avg": { // 计算0-100区间内的平均值(区别于app_group内部的aggs)
            "field": "costTime"
          }
        }
      }
    }
  }
}
```

4. 计算时间段内,各个APP的SQL执行时间平均值。引入date histogram,同上,是进行bucket分组的操作。

```json
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        }
      ]
    }
  },
  "aggs": {
    "dateTime": {
      "date_histogram": {
        "field": "@timestamp", //划分时间的字段
        "interval": "hour", // 步长
        "min_doc_count": 1 // 某时间区间的文档最小数量,防止某个无数据区间段被放弃
      },
      "aggs": {
        "app_group": {
          "terms": {
            "field": "APP.keyword"
          },
          "aggs": {
            "avg_time": {
              "avg": {
                "field": "costTime"
              }
            }
          }
        },
        "avg_time": {
          "avg": {
            "field": "costTime"
          }
        }
      }
    }
  }
}
```

5. 某应用的SQL执行时间与整个系统所有SQL执行时间进行对比分析。引入:global bucket概念。

```json
{
  "size": 0,
  "query": { //确定聚合的scope, app=m-bs-orgmanage,且ExecSQL存在
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        },
        {
          "match_phrase": {
            "APP": "m-bs-orgmanage"
          }
        }
      ]
    }
  },
  "aggs": {
    "app_avg_time": { //计算scope下的平均值
      "avg": {
        "field": "costTime"
      }
    },
    "allApp_avg_time": { //重新建立bucket
      "global": {}, // 明确使用所有文档,json体为空
      "aggs": { // 在global.scope下计算聚合
        "avg": {
          "avg": {
            "field": "costTime"
          }
        }
      }
    }
  }
}
```

6. 应用内,执行时间小于500ms的SQL,计算平均值;执行时间在500-1000ms的SQL,计算其平均值;执行之间大于1000ms的SQL,计算平均值。引入aggs.filter,表示在桶内执行的filter(局部过滤)。

```json
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "ExecSQL"
          }
        }
      ]
    }
  },
  "aggs": {
    "lte500": {
      "filter": {
        "range": {
          "costTime": {
            "lte": 500
          }
        }
      },
      "aggs": {
        "avg_time": {
          "avg": {
            "field": "costTime"
          }
        }
      }
    },
    "500-1000": {
      "filter": {
        "range": {
          "costTime": {
            "gt": 500,
            "lte": 1000
          }
        }
      },
      "aggs": {
        "avg_time": {
          "avg": {
            "field": "costTime"
          }
        }
      }
    },
    "gt1000": {
      "filter": {
        "range": {
          "costTime": {
            "gt": 1000
          }
        }
      },
      "aggs": {
        "avg_time": {
          "avg": {
            "field": "costTime"
          }
        }
      }
    }
  }
}

```


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值