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

用过 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容