查询与过滤
Elasticsearch中的数据检索分为两种情况:查询和过滤。
Query查询会对检索结果进行评分,注重的点是匹配程度,例如检索“运维咖啡吧”与文档的标题有多匹配,计算的是查询与文档的相关程度,计算完成之后会算出一个评分,记录在_score字段中,并最终按照_score字段来对所有检索到的文档进行排序
Filter过滤不会对检索结果进行评分,注重的点是是否匹配,例如检索“运维咖啡吧”是否匹配文档的标题,结果只有匹配或者不匹配,因为只是对结果进行简单的匹配,所以计算起来也非常快,并且过滤的结果会被缓存到内存中,性能要比Query查询高很多
一个最简单的DSL查询表达式如下:
GET /_search { "query":{ "match_all": {} } } 复制代码
/_search 查找整个ES中所有索引的内容
query 为查询关键字,类似的还有aggs为聚合关键字
match_all 匹配所有的文档,也可以写match_none不匹配任何文档
全文查询
上边有用到一个match_all的全文查询关键字,match_all为查询所有记录,常用的查询关键字在ES中还有以下几个最简单的查询,下边的例子就表示查找title为My second blog entry的所有记录
- match_all
POST /website/_search { "query":{ "match": { "title":"My second blog entry" } } } 复制代码
- multi_match 在多个字段上执行相同的match查询,下边的例子就表示查询host或http_referer字段中包含ops-coffee.cn的记录
POST /website/_search { "query":{ "multi_match": { "query":"My second blog entry", "fields":["title","text"] } } } 复制代码
就是查多个字段含义相同的词
- query_string
POST /website/_search { "query":{ "query_string": { "query":"(My second blog entry) OR (My fist blog entry)", "fields":["host"] } } } 复制代码
- term
term可以用来精确匹配,精确匹配的值可以是数字、时间、布尔值或者是设置了not_analyzed不分词的字符串 复制代码
GET /ops-coffee-2019.05.14/_search { "query":{ "term": { "status": { "value": 404 } } } } 复制代码
term对输入的文本不进行分析,直接精确匹配输出结果,如果要同时匹配多个值可以使用terms
GET /ops-coffee-2019.05.14/_search { "query": { "terms": { "status":[403,404] } } } 复制代码
- range range用来查询落在指定区间内的数字或者时间
GET /ops-coffee-2019.05.14/_search { "query": { "range":{ "status":{ "gte": 400, "lte": 599 } } } } 复制代码
以上表示搜索所有状态为400到599之间的数据,这里的操作符主要有四个gt大于,gte大于等于,lt小于,lte小于等于
当使用日期作为范围查询时,我们需要注意下日期的格式,官方支持的日期格式主要有两种
时间戳,注意是毫秒粒度
GET /ops-coffee-2019.05.14/_search { "query": { "range": { "@timestamp": { "gte": 1557676800000, "lte": 1557680400000, "format":"epoch_millis" } } } } 复制代码
日期字符串
GET /ops-coffee-2019.05.14/_search { "query": { "range":{ "@timestamp":{ "gte": "2019-05-13 18:30:00", "lte": "2019-05-14", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd", "time_zone": "+08:00" } } } } 复制代码
组合查询
通常我们可能需要将很多个条件组合在一起查出最后的结果,这个时候就需要使用ES提供的bool来实现了
例如我们要查询host为ops-coffee.cn且http_x_forworded_for为111.18.78.128且status不为200的所有数据就可以使用下边的语句
GET /ops-coffee-2019.05.14/_search { "query":{ "bool": { "filter": [ {"match": { "host": "ops-coffee.cn" }}, {"match": { "http_x_forwarded_for": "111.18.78.128" }} ], "must_not": { "match": { "status": 200 } } } } } 复制代码
主要有四个关键字来组合查询之间的关系,分别为:
must: 类似于SQL中的AND,必须包含
must_not: 类似于SQL中的NOT,必须不包含
should: 满足这些条件中的任何条件都会增加评分_score,不满足也不影响,should只会影响查询结果的_score值,并不会影响结果的内容
filter: 与must相似,但不会对结果进行相关性评分_score,大多数情况下我们对于日志的需求都无相关性的要求,所以建议查询的过程中多用filter
结尾
稍微讲了一下DSL,下次我们结合项目来做一下最简单的增删改查,这样就会好很多,下章节我们讲讲我们公司用的Java 客户端highlevelclient