相关文章推荐
大力的跑步机  ·  SQL 基础--> ...·  1 年前    · 
追风的炒粉  ·  java - How can I pass ...·  1 年前    · 

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

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

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

String当中与获取相关的常用方法有: public int length():获取字符串当中含有的字符个数,拿到字符串长度。 public String concat(String str):将当前字符串和参数字符串拼接成为返回值新的字符串。 public char charAt(int index);获取指定索引位置的单个字符。(索引从0开始。) public int index0f(Stringstr):查找参数字符串在本字符串当中首次出现的索引位置,如果 没有返回-1值。
Java 的 String、StringBuffer 和 StringBuilder(一文讲透)
Java 的 String、StringBuffer 和 StringBuilder(一文讲透)
告别StringUtil:使用Java 全新String API优化你的代码
Java 编程语言的每一次重要更新,都引入了许多新功能和改进。 并且在String 类中引入了一些新的方法,能够更好地满足开发的需求,提高编程效率。
(ElasticsSearch学习)歌词检索Demo的实现:二. 搭建spring boot+spring data+jest+elasticsearch环境,实现歌词的全文检索