美文网首页
Kibana顶部的那个输入框你知道怎么用吗?

Kibana顶部的那个输入框你知道怎么用吗?

作者: rockybean | 来源:发表于2019-10-12 09:18 被阅读0次

    用过 Kibana 的同学应该都注意过其顶部的搜索框,像下图这样。

    image

    这个输入框接受符合 query string 语法的查询语句。在日常开发中我们常用的都是 elastic query dsl(domain specific language),都是 json 格式的,像下面这个简单的查询语句。

    {
        "query":{
            "match":{
                "name":"elastic"
            }
        }
    }
    

    这个查询如果用 query string 来表示的话,如下所示:

    name:elastic
    

    看起来是不是简洁了很多呢?对于 kibana 这种 UI 界面,输入越是简单,越是接近自然语言,对于用户也就越是友好,所以 kibana 的搜索框默认选择了 query string 的搜索语法。虽然 query string 展示起来简洁了很多,但是要用好却没有那么简单,如果不好好阅读官方文档并做实验,那你会吃不少苦头。下面我就来帮大家扫清障碍。

    注解:

    如果非要用 query dsl 的话,kibana 也是支持的,你只需要把 query 中的内容放到搜索框中就可以了,比如上面的查询语句,你只要放下面的内容就可以查询了。

    {    
        "match":{    
            "name":"elastic"
        }
    }
    

    由来

    elasticsearchquery string 其实就是 lucenequery languageelasticsearch 本身就是构建于 lucene 之上的,它支持 lucenequery language 也是很简单的事情。那这个 query language 是怎么来的呢?根据 lucene 文档中介绍,虽然 lucene 已经提供了构建查询条件的 API,但对于人类直接使用而言不够友好和自然,所以 lucene 提供了这样一种接近自然语言的查询语言,方便人工输入和记忆查询条件。lucene 不鼓励在代码中直接使用 query language,因为它还要经过一层 query parser 的转换,有性能损耗,另外 query language 也只覆盖了一部分查询 API,并不完备。

    基本概念

    这里先讲解两个术语: single termphrase。前者是指单个词(分词后的最小单位),后者指短语。举例来说,wordsun 这些都是 single term,而用双引号包裹起来 “word sun“ 就成了 phrase 。所以这两者的区别在于 phrase 是由 term 组成的,包裹在双引号中。而 phrase 中的词在匹配是有顺序要求的,这也就是 elasticsearchmatch querymatch phrase query 的区别之一。

    接下来再看一个术语:field,也就是字段。我们在使用 query dsl 来写搜索条件时,都会指明是要在哪一个 field 上做匹配。同理,在 query string 中也可以做到只匹配指定的 field,用法是将 字段名称: 放到查询内容前面即可,比如 name:tom。当不指定 field 时,会使用默认的 field,默认配置为 _all字段,这个是可以自己指定的(index.query.default_field)。关于 _all 字段,可以简单理解为所有文档字段的拼接结果,这里就不展开讲了。比如下面这个查询语句就是查询 nametom 的所有文档。

    name:tom
    

    如果不写 name: ,只写 tom,那么相当于执行 _all:tom 这个查询。

    另外* field* 是有作用域的,只对紧跟其后的 term 生效。

    name:"Tom Lee"
    

    上面这是一个 phrase 查询,查询匹配 Tom Lee 的所有文档。

    name:Tom Lee
    

    上面这个查询实际等效于

    name:Tom OR _all:Lee
    

    这也是在实际使用中很多人容易踩坑的地方,使用的过程中要切记,否则查询出的结果肯定不会如你预期的那样。

    如果你想对一个 field 指定复杂的查询条件,那么可以使用括号将查询条件包起来用(field grouping)。比如下面的这个语句:

    name:(tom lee)
    

    等价于

    name:(tom OR lee)
    

    查询 nametom 或者 lee的所有文档。

    另外括号不仅可以作用在 field 上,还可以作用在外层的逻辑处理中。比如下面这种查询组合也是支持的(大家先忽略还没有讲到的操作符)。

    (name:tom && age:10)||city:(shanghai beijing)
    

    有心的读者可能会发现为什么 && 的语句还要加括号呢,它的优先级不是比 || 高吗?我 也是这么认为的,但动手测试后发现貌似 lucene 没有实现这个优先级的解析,所以大家使用的时候注意括号的使用。

    下面再讲一下布尔操作符,大家对这个应该很熟悉了,比如 ANDORNOT等。这里要注意的一点是:query string 中的布尔操作符必须大写。如果小写,比如 andornotquery解析器会把他们当做普通 term 解析。比如下面这个语句:

    name:tom and age:10
    

    上面的查询实际对应下面的语句:

    name:tom OR _all:and OR age:10
    

    爱思考的同学看到上面的解释应该就有疑问了。

    “这个 OR 是从哪里来的呢?”
    

    这个 OR 是默认的布尔操作符,当多个查询条件之间没有指定布尔关系时,就会使用 OR

    另外可以用 &&||* 分别代替 ANDOR,使得查询语句更简洁易懂。

    NOT 就是非操作,简写符号为 !。用法如下:

    name:(tom NOT lee)
    

    查询 nametom,但不是 lee 的所有文档。

    除去 ANDORNOTquery string 还支持 +-,分别对应 mustmust not 的含义。

    name:(tom +lee -alfred)
    

    上面的语句查询 name 中 含有 lee,不含有 alfred,但可能含有 tom 的所有文档。

    大家可以想一下如果用 ANDORNOT 来重写上面的语句是什么样子呢?

    name:((lee && !alfred) || (tom && lee && !alfred))
    

    你是不是发现 +- 的好处了?

    查询功能

    讲完基础概念,我们再来看看 query string 支持的几个查询功能。

    范围查询 range search

    数字、日期类型等都是可以指定范围的,对于这类可以使用范围查询,闭区间用[],开区间用{}。举几个例子大家一看就明白了。

    age:[1 TO 10] 意为 1<=age<=10
    age:[1 TO 10} 意为 1<=age<10
    age:[1 TO ] 意为 age>=1
    age:[* TO 10] 意为 age<=10
    

    日期也是一样的用法,只要将数字替换为 2017-01-01 即可。

    如果你觉得这样写太麻烦了,那可以使用简略写法,如下:

    age:(>=1 && <=10) 或者 age:(+>=1 +<=10)
    age:(>=1 && <10) 或者 age:(+>=1 +<10)
    age:>=1
    age:<=10
    

    通配符查询 wildcard search

    大家对于通配符应该都不陌生,有 ? 和 * 两个,前者代表一个字符,后者代表0或多个字符。

    name:t?m
    name:tom*
    name:t*m
    

    上面的使用方式都可以,但是不能把 ? 和 *** 放在最前面,因为这会导致 elasticsearch 将所有的分词都比对一遍,效率低下。

    通配符查询的效率很低,也会占用较多的内存(因为要把所有符合条件的分词进行比对),建议大家谨慎使用。

    正则查询 regular expressionsearch

    正则查询如同字面意义所讲的,支持正则表达式进行匹配。

    name:/[mb]oat/
    

    但这里并不支持所有的正则语法,使用的时候要注意查看官方文档说明。另外正则查询的内存压力也很大,要谨慎使用。

    模糊查询 fuzzy search

    所谓模糊查询是指允许搜索和匹配的词(term)之间有差异,比如搜索 surprize,可以匹配到surprise

    name:roam~
    

    上面的语句会匹配到 foamroams,波浪号后面可以指定一个 0~2 的浮点值,用以表示模糊度,我在实际使用中用的不多,就不展开来讲了。

    近似度查询 proximity search

    所谓近似度查询是指在一个短语(phrase)中,词(term)与词之间距离的匹配。

    name:"tom lee"~2
    

    匹配时允许 tomlee 之间有 2 个词的距离,笔者用的也不多,所以不班门弄斧了。

    提升查询权重 boosting term

    查询时如果想改变某个查询条件的权重,可以使用 ^ 来实现。

    name:(tom^4 lee)
    

    上面的查询表示,当 name 中包含 tom 时,其权重是 lee 的4倍,这就意味着相应得分也会高,排序也会靠前。

    特殊字符过滤

    query string 本身已经占据了一些关键字,如下

    + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
    

    当遇到这些关键词时,需要使用 \ 做转义,比如如果你要搜索 (1+1):2,那么查询条件需要写成\(1\+1\)\:2

    总结

    至此,query string就讲完了,大家可以去愉快地和 kibana 玩耍了,遇到问题时欢迎和笔者我讨论哦~

    参考文档

    1. https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax

    2. https://www.timroes.de/2016/05/29/elasticsearch-kibana-queries-in-depth-tutorial/

    3. http://lucene.apache.org/core/6_4_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description

    4. http://www.lucenetutorial.com/lucene-query-syntax.html

    相关文章

      网友评论

          本文标题:Kibana顶部的那个输入框你知道怎么用吗?

          本文链接:https://www.haomeiwen.com/subject/ajwxuctx.html