大神都这么做,让 Kibana 搜索语法 query string 也能轻松上手

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: kibana 的搜索框默认选择了 query string 的搜索语法,虽然简洁却不简单,本文来帮大家如何轻松上手;

作者介绍

魏彬,普翔科技 CTO,开源软件爱好者,中国第一位 Elastic 认证工程师,《Elastic日报》和 《ElasticTalk》社区项目发起人,被 elastic 中国公司授予 2019 年度合作伙伴架构师特别贡献奖。对 Elasticsearch、Kibana、Beats、Logstash、Grafana 等开源软件有丰富的实践经验,为零售、金融、保险、证券、科技等众多行业的客户提供过咨询和培训服务,帮助客户在实际业务中找准开源软件的定位,实现从 0 到 1 的落地、从 1 到 N 的拓展,产生实际的业务价值。

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

image.png

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

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

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

ame:elastic

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

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

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

由来

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

基本概念

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

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

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)

查询 name 为 tom 或者 lee的所有文档。

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

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

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

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

name:tom and age:10

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

name:tom OR _all:and OR age:10

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

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

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

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

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

name:(tom NOT lee)

查询 name 为 tom,但不是 lee 的所有文档。

除去 AND、OR、NOT ,query string 还支持 + 和 -,分别对应 must 和 must not 的含义。

name:(tom +lee -alfred)

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

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

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~

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

近似度查询 proximity search

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

name:"tom lee"~2

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

提升查询权重 boosting term

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

name:(tom^4 lee)

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

特殊字符过滤

uery 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顶部的那个输入框你知道怎么用吗?》作者“魏彬”授权转载,对未经许可擅自使用者,保留追究其法律责任的权利。


image.png

阿里云Elastic Stack】100%兼容开源ES,独有9大能力,提供免费X-pack服务(单节点价值$6000)

相关活动


更多折扣活动,请访问阿里云 Elasticsearch 官网

阿里云 Elasticsearch 商业通用版,1核2G ,SSD 20G首月免费
阿里云 Logstash 2核4G首月免费


image.png

image.png

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
6月前
|
存储 C++ 容器
【C++从练气到飞升】09---string语法指南(二)
【C++从练气到飞升】09---string语法指南(二)
|
6月前
|
存储 Linux C语言
【C++从练气到飞升】09---string语法指南(一)
【C++从练气到飞升】09---string语法指南(一)
|
6月前
|
Java
String.format 的基本语法
`String.format` 是 Java 中的一个方法,用于格式化字符串。这个方法可以接受一个或多个参数,并根据指定的格式将它们格式化为字符串。 以下是 `String.format` 的基本语法: ```java String formattedString = String.format(formatString, arguments); ``` 其中: * `formatString` 是一个包含格式说明符的字符串。 * `arguments` 是要插入到格式字符串中的参数。 例如,假设我们想将两个整数格式化为一个字符串,其中整数之间用逗号分隔: ```java int
176 2
|
6月前
|
存储 Java 索引
【Java SE语法篇】10.String类
【Java SE语法篇】10.String类
|
6月前
|
JavaScript 前端开发
js基础语法:包括变量声明、数据类型(Number, String, Boolean, Null, Undefined, Symbol, Object)、运算符、流程控制语句(if...else, switch, for, while, do...while)等。具体案例使用演示
js基础语法:包括变量声明、数据类型(Number, String, Boolean, Null, Undefined, Symbol, Object)、运算符、流程控制语句(if...else, switch, for, while, do...while)等。具体案例使用演示
73 1
|
6月前
|
JavaScript 前端开发
JavaScript基础语法:包括变量声明、数据类型(Number, String, Boolean, Null, Undefined, Symbol, Object)、运算符、流程控制语句(if...else, switch, for, while, do...while)等。
JavaScript基础语法:包括变量声明、数据类型(Number, String, Boolean, Null, Undefined, Symbol, Object)、运算符、流程控制语句(if...else, switch, for, while, do...while)等。
63 0
|
存储 C语言 C++
C++中String的语法及常用接口用法
在C语言中,string是一个标准库类(class),用于处理字符串,它提供了一种更高级、更便捷的字符串操作方式,string 类提供了一系列成员函数和重载运算符,以便于对字符串进行操作和处理。
|
存储 安全 Java
【JavaSE】String类的重点语法知识汇总
【JavaSE】String类的重点语法知识汇总
|
存储 安全 Java
【JavaSE】Java基础语法(三十七):Java 中的 String 类(源码级别)(2)
2.11 char[] toCharArray() 2.12 String substring(int beginIndex) 从传入的索引处截取,截取到末尾,得到新的字符串 2.13 String substring(int beginIndex, int endIndex) 根据开始和结束索引进行截取,得到新的字 符串(包含头,不包含尾)
|
存储 Java
【JavaSE】Java基础语法(三十七):Java 中的 String 类(源码级别)(1)
String 表示 字符串类型,属于 引用数据类型 。Java 中 String 是 不可变 的。 在 Java 当中 双引号 括起来的字符串,是直接存储在“方法区”的“字符串常量池”当中的。 1. 构造方法 1.1 String()