虽然通过文档_id可以获取到文档,但_id字段一般都是一个无意义的值,在实际应用中更多地是使用文档其它有意义字段做检索。Elasticsearch提供一个专门用于检索的_search接口,这个接口可以根据指定的查询条件检索文档,Elasticsearch强大的检索能力都体现在对这个接口的应用上。除了本文介绍的文档检索基于_search接口,《Elastic Stack应用宝典》这本书中第6章介绍的聚集查询也是基于这个接口,只是使用的参数及格式不同而已。
Elasticsearch可用于文档检索的接口除了_search以外,还包括_count、_msearch、_scripts等。此外,还有一组辅助文档检索的接口可供使用。它们可以查看检索执行情况,为性能调优提供依据,包括_validate、_explain、_field_caps、_search_shards等。
由于_search接口比较重要,本文会以先介绍这个接口的使用方法,然后再介绍接口在检索文档时可用的一些重要参数,其余接口将统一放在最后介绍。本文所有示例都将使用Kibana样例数据,请读者在学习之前确保这些数据已经导入。
_search接口
_search接口可以使用GET或POST方法请求,在请求路径中可以指定一个或多个索引,还可以使用_all或者星号“*”匹配所有索引。如果不指定索引名称,实际上也是匹配所有索引。Elasticsearch为使用这个接口定义了一种查询语言DSL(Domain Specific Language)。DSL是一套基于JSON的查询语言,这种只在某一领域使用的语言通常称为领域特定语言,而它们英文单词首字母简写就是DSL。《Elastic Stack应用宝典》这本书的后续章节都将简称这种语言为DSL,由于DSL内容非常庞杂,将在书中第5章单独介绍。
_search接口有两种请求方式,一种是基于URI的请求方式,另一种则是基于请求体的请求方式。无论是哪一种,它们执行的语法根基都是DSL,只是在使用形式上不同而已。
基于URI
_search接口基于URI的请求方式比较简单,DSL查询条件以请求参数q传递给接口。使用_search接口的最简形式就是不挂任何参数直接调用,可以在路径中添加索引名称,也可以不添加。所以示例1中的请求都是正确的:
GET _search
POST _search
GET kibana_sample_data_logs/_search?q=message:chrome firefox
示例1 基于URI的_search接口调用
在最后一个请求中,参数q定义的内容叫查询字符串(Query String),它的含义是检索message字段值中包含chrome或firefox的文档。查询字符串不仅可以在基于URI的检索中使用,也可以在基于请求体的检索中使用,是DSL定义的一种检索方法。查询字符串属于全文检索,这意味着查询字符串在检索前会被分析器解析为一系列词项和运算符。以示例1中的请求为例,“chrome firefox”会被解析为chrome和firefox两个词项,然后再与message字段的词项索引做匹配。只要message字段中包含chrome或firefox,这个文档就满足查询条件。
查询字符串
查询字符串的基本格式为“<字段名>:<查询值>”,其中字段名可以指定,也可以不指定。如果没有指定字段名,要匹配的字段由index.query.default_field参数设置。这个参数的默认值为*.*,即在所有字段中查询。此外,还可以使用参数df(Default Field)指定要查询的字段名,它与参数q一样是可以用在URI中的参数。如果指定了字段名,查询将在指定字段中匹配词项。除了直接指定字段名以外,还可使用通配符等形式匹配字段,例如:
GET kibana_sample_data_logs/_search?q=geo.\*:CN US
GET kibana_sample_data_logs/_search?q=_exists_:geo
示例2 特殊格式的字段名
在示例2中,查询字符串“geo.*:CN US”将在geo的子字段中匹配CN或US。第二个查询字符串中的_exists_不是一个具体的字段名,而是代表所有非空的title字段。
下面再来看看查询字符串中的查询值。查询值会在检索前通过分析器拆分为词项,在检索时只要字段中包含任意一个词项就视为满足条件。在实现上,这其实是使用了DSL语言中定义的match查询。如果使用双引号将它们括起来,_search接口将使用DSL的match_phrase做短语匹配。从效果上看就类似于用整个短语做检索,而不是使用单个词项做检索。查询值中除了包含词项本身以外,还可以包含操作符OR和AND,注意它们必须大写否则将被识别为词项。例如,“(tom smith) AND jhon”代表的含义是同时包含tom、jhon或smith、jhon的字段。除了可以包含词项、操作符以外,查询字符串的查询值中还可以包含通配符、正则表达式等。表1给出了一些可能的用法:
请求参数
基于URI调用_search接口时可以使用的参数,除了前述的q和df以外还有很多。例如,_source参数可以用来设置在返回结果中是否包含_source字段,还可以使用_source_include或_source_exclude参数包含或排除源文档的字段。这样的参数还有很多,它们大多数与基于请求体的参数具有相同的名称和含义。不仅如此,部分参数对于其它接口也可使用,所以对于参数的介绍将在本文下一阶段统一讲解。表2先将这些参数总结出来供参考&#