Kibana搜索原理

注:本文基于Kibana 7.13.4版本

1. 背景

在上一篇文章——Kibana常用搜索语法,我们简单介绍了kibana的常用搜索语法,但在实际使用中,总是出现各种异常,为什么明明存在的字符串就是匹配不到,搜不出来,今天我们就来稍微深入下Kibana的搜索原理。

2. 关于Kibana的正则表达式

因为Kibana的正则表达式引擎并不是使用perl pcre,因此有一些正则并不支持,比如开头和结尾锚定符号,^和$,详细的支持符号可以查看官方文档,https://www.elastic.co/guide/en/elasticsearch/reference/7.13/regexp-syntax.html

3. 数据字段类型

我们的日志,每个字段都有对应的数据类型,而不同的数据类型也决定了该字段的搜索属性,比如是否允许全文搜索。关于Kibana支持的数据类型可以参考官方文档,https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
我们今天主要来看下text类型和keyword类型,这两个类型也是导致我们搜索结果不符合预期的主要原因。

  • keyword
    保留字段原格式,不进行解析,搜索时需要匹配到整个字段,比如对于一个字段为"how are you",你无法用how或者are来搜索,只能用完整的“how are you”来搜索,或者使用正则和通配符,比如how*

  • text
    可以被分析,也就是能支持全文搜索,比如对于一个字段为"how are you",它就会被解析为

“how” "are" "you"

那我们搜索时,就可以通过这三个词中的任意一个来搜索

4. mapping

既然每个字段都有对应的类型,那如何确定或者如何设置某个字段的类型呢,这就需要通过mapping。所谓mapping就是将传入的日志通过一定规则将每个字段映射成对应的类型。而这个规则就是我们需要关注的。

我们可以通过Kibana的Dev Tools来创建index并设置对应的mapping规则,

PUT mytest
{
  "mappings": {
    "properties": {
      "message1": {
        "type": "text"
      },
      "message2": {
        "type": "keyword"
      }
    }
  }
}

如上,我们定义了新的index为mytest,有两个字段,分别是text类型的message1和keyword类型的message2。对于已存在的index,我们可以通过get方式获取详细的mapping规则,

GET /mytest/_mapping

5. analyze

上面我们说到,对于text类型的字段是可解析的,可以被全文搜索,那我们又如何来确定这个全文搜索的最小粒度呢。比如“how are you”这个文本我们很好理解,最小粒度就是一个单词。但如果对于复杂一些的字符串呢,比如“/var/log/yum.log”。这就涉及到分词,也就是对字符串的解析。Kibana默认的分析器为standard analyzer,其遵循的分词规范为Unicode® Standard Annex #29,具体规则我们不细说。我们主要是关注分词的结果,同样可以通过Kibana的Dev Tools来测试。

可以通过以下方式获取指定文本的解析分词结果,用GET请求也一样。

POST _analyze
{
  "analyzer": "standard",
  "text": "/var/log/yum.log"
}

有结果可知,这个文本被分为三部分,所以我们搜索该文本时,应该用yum.log,而不是yum,否则就搜索不到
Kibana搜索原理

6. 简单实践

说完这些,我们通过一个小例子来说明,这样理解起来比较直接。需要注意的是,以下测试都是在Lucene开启的情况下测试。

首先我们以第四部分的mapping为例子,创建mytest索引和mapping规则,然后我们创建几条数据,用于接下来的测试,

PUT mytest/_doc/1?refresh
{
  "message1": "hello world",
  "message2":"how are you" 
} 

PUT mytest/_doc/2?refresh
{
  "message1": "how are you",
  "message2":"hello world" 
} 

PUT mytest/_doc/3?refresh
{
  "message1": "/var/log/yum.log",
  "message2":"path" 
} 

然后我们创建index pattern,把mytest导入,就能看到这三条文档,
Kibana搜索原理

这样我们就可以开始我们的测试了。

  • text
message1:helloworld #返回第一条文档
message1:hello #无文档返回
message1:how #返回第二条文档
message1:are #返回第二条文档
message1:var #返回第三条文档
message1:yum.log #返回第三条文档
message1:yum #无文档返回
message1:yum* #返回第三条文档
  • keyword
message2:"how are you" #返回第一条文档
message2:how #无文档返回
message2:how* #返回第一条文档
message2:are* #无文档返回
message2:*are* #返回第一条文档
message2:helloworld #返回第二条文档

参考文档:

  1. https://*.com/questions/52908780/kibana-using-regex-doesnt-work-as-expected
  2. https://www.elastic.co/guide/en/elasticsearch/reference/7.13/regexp-syntax.html
  3. https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
  4. https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-analyze.html
上一篇:ELK-logstash收集日志


下一篇:使用ELK搭建日志平台(四):使用 OpenTelemetry SDK