elsticsearch 日志分析系统学习

文档 Document
用户存储在es中的数据文档
索引 Index
由具有相同字段的文档列表
查看当前所有索引
GET /_cat/indince

节点Node
一个Elasticsearch的运行实例,是集群
集群master


elasticsearch
-----

Document
Json Object
数据类型:
字符串:text,keyword
数值型:long,integer,short,byte,double,float,half_float,scaled_float
布尔:boolean
日期:date
二进制:binary
范围类型:integer_range,float_range,long_range,double_range,date_range

每个文档都有唯一的id标识
-example

{
"remote_ip":"10.10.10.10",
...
}

元数据,用于标注文档的相关信息

- _index:文档所在的索引名
- _type: 文档所在的类型名
- _id: 文档唯一id
- _uid:组合id,由_type和_id组成(6.x _type不再起作用)
- _source:文档的原始Json数据,可以从这里获取每个字段的内容
- _all:整合所有字段内容到该字段,默认禁用


正排索引:
文档id 文档内容
  1 es搜索引擎
  2 php语言
  3 搜索引擎的诞生

倒排索引:
  单词 文档ID列表
  es 1
  搜索引擎 1,3
  php 2


es自带的分词器
  - Standard:
  - 默认分词器
  特性:
  - 按词切分,支持多语言
  - 小写处理

- Simple:
特性:
- 按照非字母切分
- 小写处理
- 会把下划线,单引号也都处理掉
- Whitespace
特性:
- 按照空格切分

- Stop
特性:
- 会把语气助词等修饰性的词语都处理掉
- 其他和simple一直
- Keyword
特性:
- 不分词, 直接将输入作为一个单词输出
- Pattern
特性:
- 通过正则表达式自定义分割符
- 默认是w+, 即非字词的符号作为分隔符
- Language
- 提供了30+ 常见语言的分词器

中文分词:
难点 汉语中词没有一个形式上的分界符
常用分词系统
- IK
- 实现中英文单词的切分,支持IK_smart、 ik_maxword等模式
- 可自定义词库,支持热更新分词词典

- jieba
- python中最流行的分词系统,支持分词和词性标注
- 支持繁体分词、自定义词典、并行分词等

自定义分词
当自带的分词无法满足需求时,可以自定义分词
- 通过自定义 Character Filters、 Tokenizer 和 Token Filter 实现

Character Filters
- 在 Tokenizer 之前对原始文本进行处理,比如增加、删除或替换字符等
-自带的如下:
- HTML Strip 去除html标签和转换 html 实体
- Mapping 进行字符替换操作
- Pattern Replace 进行正则匹配替换
- 会影响后续 tokenizer 解析的postion 和offset 信息

Tokenizer
- 将原始文本按照一定规则切分为单词(term or token)
- 自带的如下:
- standard 按照单词进行分割
- letter 按照费字符类进行分割
- whitespace 按照空格进行分割
- UAX URL Email 按照standard 分割, 但不会分割邮箱和url
- NGram 和Edge NGram 连词分割
- Path Hierarchy 按照文件路径进行切割

Token Filters
- 对于 tokenizer 输出的单词(term) 进行增加、删除、修改等操作
- 自带的如下:
- lowercase将所有term 转换为小写
- stop 删除 stop words
- NGram 和 Edge NGram 连词分割
- Synonym 添加近义词的term


Mapping:
1、类似数据库的表结构定义,主要作用是:
-定义Index下的字段名(Filed Name)
-定义字段的类型, 比如数值型、字符串型、布尔型等
-定义倒排索引相关的配置,比如是否索引、记录position等
example:
GET /test_index/_mapping
{
"test_index":{ #索引名
"mappings":{
"doc":{ #type
"properties":{ #他下面指的是所有的字段
"age":{
"type":"integer"
},
"username":{
"type":"keyword" #不分词
}
}
}
}
}
}


自定义Mapping的api:
request请求:
PUT my_index
{
"test_index":{ #索引名
"mappings":{
"doc":{ #type
"properties":{ #他下面指的是所有的字段
"age":{
"type":"integer"
},
"name":{
"type":"keyword" #不分词
},
"title":"text"
}
}
}
}
}

response 返回结果 {"acknoeledged":ture,
"shards_acknowledged":true,
"index":"my_index"
}
Mapping中的字段类型一旦设定后,禁止直接修改,原因如下:
- Lucene 实现的倒排索引生成后不允许修改
重新建立新的索引,然后做reindex操作

允许新增字段
通过dynamic参数来控制字段的新增
- true(默认) 允许自动新增字段
- false 不允许自动新增字段,但是文档可以 正常写入,但无法对字段进行查询等操作
- strict 文档不能写入, 报错
PUT my_index
{
"mappings":{
"my_type":{
"dynamic":false,
"properties":{
"user":{
"properties":{
"name":{
"type": "text"
},
"social_networks":{
"dynamic":true,
"properties":{}
}
}
}
}
}
}
}

索引模板,Index Template, 主义熬用于在新建索引时自动应用预先设定的配置,简化索引创建的操作步骤
- 可以设定索引的配置和mapping
- 可以有多个模板,根据order设置,order大的覆盖小的配置


index
- 控制当前字段是否索引,默认为true,即记录索引,false不记录,即不可搜索


index_options 用于控制倒排索记录的内容,有如下4中配置
- docs只记录 doc id
- freqs 记录 doc id 和 term frequencies
- positions 记录 doc id、 term frequencies 和 term position
- offsets 记录 doc id、 term frequencies、 term position 和character offsets

text类型默认配置为positons,其他默认为docs
记录内容越多,占用空间越大

null_value
-当字段遇到null值时的处理策略,默认为null,即空值,此时es会忽略该值。可以通过设定该值设定字段的默认值
PUT my_index
{
"mappings":{
"my_type":{
"properties":{
"status_code":{
"type": "keyword",
"null_value":"NULL" #设定默认值为NULL
}
}
}
}

}

数据类型
核心数据类型
- 字符串型: text、 keyword
- 数值型 long、 integer、short、byte、double、float、half_float、scaled_float
- 日期类型 date
- 布尔类型 boolean
- 二进制类型 binary
- 范围类型 integer_range、float_range、long_range、double_range、date_range

复杂数据类型
- 数组类型 array
- 对象类型 object
- 嵌套类型 nested object
地理位置数据类型:
- geo_point
- geo_shape
专用类型
- 记录ip地址 ip
- 实现自动补全 comletion
- 记录分词数 token_cout
- 记录字符串hash值 murmur3 #通过插件实现
- percolator
- join #父子查询

es是依靠JSON文档的字段类型来实现自动识别字段类型,支持的类型如下:

JSON类型 es类型

null 忽略
boolean boolean
浮点类型 float
整数 long
object object
array 由第一个非null值得类型决定
string 匹配为日期则设为date 类型(默认开启),匹配为数字的话设为float或long类型(默认关闭),设为te xt类型,并附带keyword的子字段

日期的自动识别可以自行配置日期格式,以满足各种需求
-默认是 ["strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]

- strict_date_optional_time 是ISO datetime的格式,完整格式类似下面:
- YYYY-MM0DDThh:mm:ssTZD(eg 1997-07-16T19:20:30+01:00)
- dynamic_date_formats 可以自定义日期类型
- date_detection 可以关闭日期自动识别的机制

自定义日期识别格式
PUT my_index
{
"mappings":{
"my_type":{
"dynamic_date_formats":["MM/dd/yyyy"]
}
}
}

关闭日期自动识别机制

PUT my_index
{
"mappings":{
"my_type":{
"date_detection":false
}
}
}

字符串是数字时,默认不会自动识别为整型,因为字符串中出现数字是完全合理的
- numeric_detection 可以开启字符串中数字的自动识别,如下所示:

PUT my_index
{
"mappings":{
"my_type":{
"numeric_detection":true
}
}
}

Search API
实现对es中存储的数据进行查询分析,endpoint为_search,如下所示

GET /_search
GET /my_index/_search
GET /my_index1,my_index2/_search
GET /my_*/_search 指定索引查询,可以一次查询多个

查询主要有两种形式

- URI Search
- 操作简单,方便通过命令行测试
- 仅包含部分查询语法

- Request Body Search
-es 提供的完备查询语法Query DSL(Domain Specific language)

URI Search:
GET /MY_INDEX/_search?q=user:alfred
Request Body Search:
GET /my_index/_search
{
"query":{
"term":{"user":"alfred"}
}
}

Request Body Search
将查询语句通过http request body 发送到es, 主要包含如下参数
- query符合 Query DSL 语法的查询语句
- from,size
- timeout
- sort
- ...

符合Query DSL 查询语法的查询语句
GET /my_index/_search
{
"query":{
"term":{"user":"alfred"}
}
}

Query DSL
基于JSON定义的查询语言,主要包含如下两种类型:
- 字段类查询
如 term,match,range等, 只针对某一个字段进行查询
- 复合查询
如bool查询等,包含一个或多个字段类查询或者复合查询语句

---字段类查询
字段类查询主要包括一下两类:
-全文匹配
针对 text 类型的字段进行全文检索,会对查询语句先进行分词处理,如 match,match_phrase等query类型
-单词匹配
不会对查询语句做分词处理,直接去匹配字段的倒排索引,如term,terms,range等query类型

match query 流程
GET test_search_index/_search
#operator参数可以控制但此件的匹配关系,可选项为or和and
{
"query":{
"match":{
"username":{
"query":"java ruby",
"operator":"and"
}
}
}
}
GET test_search_index/_search
#通过minimum_should_match 参数可以控制需要匹配的单词数
{
"query":{
"match":{
"job":{
"query":"java ruby enager",
"minimum_should_match":"2"
}
}
}
}

对查询语句分词
java ruby (对整个词做一次拆分)
java ruby

根据username的倒排索引进行匹配算分 (二者一致操作)
算法规则(TF/IDF BM25)
汇总得分
根据得分排序,返回匹配文档

相关性算分

相关性算分是指文档与查询语句间的相关度,英文为relevance
-通过倒排索引可以获取与查询语句相匹配的文档列表

相关性算分的几个重要概念如下:
Term Frequency(TF)词频,即单词在改文档中出现的次数。词频越高,相关度越高
Document Frequency(DF)文档频率,即单词出现的文档数
Inverse Documnet Frequency(IDF)逆向文档频率,与文档频率相反,简单理解为1/DF。即单词出现的文档数越少,相关度越高
Field-length Norm 文档越短,相关性越高

query查询时,加explain可以看到算分,排序的计算公式

Match Phrase Query 按照顺序匹配

GET test_search_index/_search
{
"query":{
"match_phrase":{
"job":"java engineer"
}
}
}

GET test_search_index/_search
{
"query":{
"match_phrase":{
"job":{
"query":"java engineer",
#可以间隔一个字段查询结构
"shop",1
}
}
}
}

Query String Query
类似于URI Search中的q参数查询
GET test_search_index/_search
{
"query":{
"query_string":{
"default_field":"username"
"query":"alfred AND way"
}
}
}

GET test_search_index/_search
{
#参数里加profile会显示查询语句
"profile":true,
"query":{
"query_string":{
"fields":["username","job"]
"query":"alfred OR (java AND ruby)"
}
}
}

Simple Query String Query
类似Query String, 但是会忽略错误的查询语法,并且仅支持部分查询语法
其常用的逻辑符号如下,不能使用AND、OR、NOT等关键词:
+ 代指 AND
| 代指 OR
- 代指NOT

Term Query
将查询语句作为整个单词进行查询,即不对查询语句做分词处理,如下所示:
GET test_search_index/_search
{
"query":{
"term":{
"username":"alfred"
}
}
}

GET test_search_index/_search
{
"query":{
"terms":{
"username":[
"alfred",
"way"
]
}
}
}

Range Query
范围查询主要针对数值和日期类型,如下所示:
GET test_search_index/_search
{
"query":{
"range":{
"age":{
"gte":10,
"lte":20
}
}
}
}
关键字: gt 大于
gte 大于等于
lt 小于
lte 小于等于

GET test_search_index/_search
{
"query":{
"range":{
"brith":{
"gte":"1990-01-01"
}
}
}
}
Query DSL - 复合查询
复合查询是指包含字段类查询或复合查询的类型,主要包括以下几类:
- constant_score query
该查询将其内部的查询结果文档得分都设定为1或者boost的值
- 多用于结合bool查询实现自定义得分
GET test_search_index/_search
{
"query":{
"constant_score":{
"filter":{ #只能有一个filter
"match":{
"username":"alfred"
}
}
}
}
}


- bool query
布尔查询由一个或多个布尔子句组成,他们都支持数组的,主要包含如下4个:
filter 只过滤符合条件的文档,不计算相关性得分
must 文档必须符合must中的所有条件,会影响相关性得分
must_not 文档必须不符合must_not 中的所有条件
should 文档可以符合should中的条件,会影响相关性得分

Filter查询值只过滤符合条件的文档,不会进行相关性算分
es正对filter会有智能缓存,因此其执行效率很高
做简单匹配查询且不考虑算分时,推荐使用filter替代query等
GET test_search_index/_search
{
"query":{
"bool":{
"filter":[
{
"term":{
"username":"alfred"
}
}
]
}
}
}
Must
两个match query文档最终得分为这两个查询得分加和
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"username":"alfred"
}
},
{
"match":{
"job":"specialist"
}
}
]
}
}
}

Must_not
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"username":"alfred"
}
}
],
"must_not":[
{
"match":{
"job":"ruby"
}
}
]
}
}
}

Should 使用分两种情况:
bool查询中只包含should,不包含must查询
bool查询中同时包含should和must查询

只包含should时,文档必须满足至少一个条件
minimum_should_match 可以控制满足条件的个数或者百分比
GET test_search_index/_search
{
"query":{
"bool":{
"should":[
{"term":{"job":"java"}},
{"term":{"job":"ruby"}},
{"term":{"job":"specialist"}}
],
"minimum_should_match":2
}
}
}
同时包含should和must时,文档不必满足should中的条件,但是如果满足条件,会增加相关性得分
GET test_search_index/_search
{
"query":{
"bool":{
"must":[
{"term":{"username":"alfred"}},
],
"should":[
{"term":{"job":"ruby"}}
]
}
}
}
query Context "VS" Filter Context
当一个查询语句位于Query或者Filter上下文时,es执行的结果会不同,对比如下:
上下文类型:query
执行类型:查找与查询语句最相关的文档,对所有文档进行相关性算分并排序
使用方法:· query
· bool中的must和should

上下文类型:Filter
执行类型:查找与查询语句相匹配的文档
使用方法:· query bool中的filter与must_not
· constant_score中的filter


- dis_max query
- function_score query
- boosting query

Count API
获取符合条件的文档数,endpoint为_count
(只获取文档数,不获取文档内容)

GET test_search_index/_count
{
"query":{
"match":{
"username":"alfred"
}
}
}

Source Filtering
过滤返回结果中_source中的字段,主要有如下几种方式:
1. GET test_search_index/_search?_source=username
2. GET test_search_index/_search
{
"source":false
}

3. GET test_search_index/_search
{
"_source":["username","age"]
}
4. GET test_search_index/_search
{
"_source":{
"includes":"i*",
"excludes":"birth"
}
}