Elasticsearch Query DSL查询入门
本篇为学习DSL时做的笔记,适合ES新手,大佬请略过~
Query DSL又叫查询表达式,是一种非常灵活又富有表现力的查询语言,采用JSON接口的方式实现丰富的查询,并使你的查询语句更灵活、更精确、更易读且易调试
查询与过滤
Elasticsearch(以下简称ES)中的数据检索分为两种情况:查询和过滤。
Query查询会对检索结果进行评分,注重的点是匹配程度,例如检索“运维咖啡吧”与文档的标题有多匹配,计算的是查询与文档的相关程度,计算完成之后会算出一个评分,记录在_score
字段中,并最终按照_score
字段来对所有检索到的文档进行排序
Filter过滤不会对检索结果进行评分,注重的点是是否匹配,例如检索“运维咖啡吧”是否匹配文档的标题,结果只有匹配或者不匹配,因为只是对结果进行简单的匹配,所以计算起来也非常快,并且过滤的结果会被缓存到内存中,性能要比Query查询高很多
简单查询
一个最简单的DSL查询表达式如下:
GET /_search { "query":{ "match_all": {} } }
/_search 查找整个ES中所有索引的内容
query 为查询关键字,类似的还有aggs
为聚合关键字
match_all 匹配所有的文档,也可以写match_none
不匹配任何文档
返回结果:
{ "took": 6729, "timed_out": false, "num_reduce_phases": 6, "_shards": { "total": 2611, "successful": 2611, "skipped": 0, "failed": 0 }, "hits": { "total": 7662397664, "max_score": 1, "hits": [ { "_index": ".kibana", "_type": "doc", "_id": "url:ec540365d822e8955cf2fa085db189c2", "_score": 1, "_source": { "type": "url", "updated_at": "2018-05-09T07:19:46.075Z", "url": { "url": "/app/kibana", "accessCount": 0, "createDate": "2018-05-09T07:19:46.075Z", "accessDate": "2018-05-09T07:19:46.075Z" } } }, ...省略其他的结果... ] } }
took: 表示我们执行整个搜索请求消耗了多少毫秒
timed_out: 表示本次查询是否超时
这里需要注意当timed_out
为True时也会返回结果,这个结果是在请求超时时ES已经获取到的数据,所以返回的这个数据可能不完整。
且当你收到timed_out
为True之后,虽然这个连接已经关闭,但在后台这个查询并没有结束,而是会继续执行
_shards: 显示查询中参与的分片信息,成功多少分片失败多少分片等
hits: 匹配到的文档的信息,其中total
表示匹配到的文档总数,max_score
为文档中所有_score
的最大值
hits中的hits
数组为查询到的文档结果,默认包含查询结果的前十个文档,每个文档都包含文档的_index
、_type
、_id
、_score
和_source
数据
结果文档默认情况下是按照相关度(_score)进行降序排列,也就是说最先返回的是相关度最高的文档,文档相关度意思是文档内容与查询条件的匹配程度,上边的查询与过滤中有介绍
指定索引
上边的查询会搜索ES中的所有索引,但我们通常情况下,只需要去固定一个或几个索引中搜索就可以了,搜索全部无疑会造成资源的浪费,在ES中可以通过以下几种方法来指定索引
- 指定一个固定的索引,
ops-coffee-nginx-2019.05.15
为索引名字
GET /ops-coffee-nginx-2019.05.15/_search
以上表示在ops-coffee-nginx-2019.05.15
索引下查找数据
- 指定多个固定索引,多个索引名字用逗号分割
GET /ops-coffee-nginx-2019.05.15,ops-coffee-nginx-2019.05.14/_search
- 用*号匹配,在匹配到的所有索引下查找数据
GET /ops-coffee-nginx-*/_search
当然这里也可以用逗号分割多个匹配索引
分页查询
上边有说到查询结果hits
默认只展示10个文档,那我们如何查询10个以后的文档呢?ES中给了size
和from
两个参数
size: 设置一次返回的结果数量,也就是hits
中的文档数量,默认为10
from: 设置从第几个结果开始往后查询,默认值为0
GET /ops-coffee-nginx-2019.05.15/_search { "size": 5, "from": 10, "query":{ "match_all": {} } }
以上查询就表示查询ops-coffee-nginx-2019.05.15
索引下的所有数据,并会在hits
中显示第11到第15个文档的数据
全文查询
上边有用到一个match_all
的全文查询关键字,match_all
为查询所有记录,常用的查询关键字在ES中还有以下几个
match
最简单的查询,下边的例子就表示查找host
为ops-coffee.cn
的所有记录
GET /ops-coffee-2019.05.15/_search { "query":{ "match": { "host":"ops-coffee.cn" } } }
multi_match
在多个字段上执行相同的match查询,下边的例子就表示查询host
或http_referer
字段中包含ops-coffee.cn
的记录
GET /ops-coffee-2019.05.15/_search { "query":{ "multi_match": { "query":"ops-coffee.cn", "fields":["host","http_referer"] } } }
query_string
可以在查询里边使用AND或者OR来完成复杂的查询,例如:
GET /ops-coffee-2019.05.15/_search { "query":{ "query_string": { "query":"(a.ops-coffee.cn) OR (b.ops-coffee.cn)", "fields":["host"] } } }
以上表示查找host为a.ops-coffee.cn
或者b.ops-coffee.cn
的所有记录
也可以用下边这种方式组合更多的条件完成更复杂的查询请求
GET /ops-coffee-2019.05.14/_search { "query":{ "query_string": { "query":"host:a.ops-coffee.cn OR (host:b.ops-coffee.cn AND status:403)" } } }
以上表示查询(host为a.ops-coffee.cn
)或者是(host为b.ops-coffee.cn
且status为403)的所有记录
与其像类似的还有个simple_query_string的关键字,可以将query_string
中的AND或OR用+
或|
这样的符号替换掉
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" } } } }
通常更推荐用这种日期字符串的方式,看起来比较清晰,日期格式可以按照自己的习惯输入,只需要format
字段指定匹配的格式,如果格式有多个就用||
分开,像例子中那样,不过我更推荐用同样的日期格式
如果日期中缺少年月日这些内容,那么缺少的部分会用unix的开始时间(即1970年1月1日)填充,当你将"format":"dd"
指定为格式时,那么"gte":10
将被转换成1970-01-10T00:00:00.000Z
elasticsearch中默认使用的是UTC时间,所以我们在使用时要通过time_zone
来设置好时区,以免出错
组合查询
通常我们可能需要将很多个条件组合在一起查出最后的结果,这个时候就需要使用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
写在最后
ES的查询博大精深,本篇文章属于基础入门,内容来源于官网
网上关于ELK搭建部署日志收集的文章很多,但收集到日志之后该如何应用这个数据宝库呢?网上仅有一些大厂分享的比较泛的概念没有实际落地的过程,我在想把这些数据利用起来,初步想法是去ES搜索出来业务或者功能的流量数据,然后做趋势分析,这不从DSL开始学习,欢迎大家加我好友找我交流,我会非常乐意
相关文章推荐阅读:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
人人都是 API 设计师:我对 RESTful API、GraphQL、RPC API 的思考
原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」。一群同频者,一起成长,一起精进,打破认知的局限性。 有一段时间没怎么写文章了,今天提笔写一篇自己对 API 设计的思考。首先,为什么写这个话题呢?其一,我阅读了《阿里研究员谷朴:API 设计最佳实践的思考》一文后受益良多,前两天并转载了这篇文章也引发了广大读者的兴趣,我觉得我应该把我自己的思考整理成文与大家一起分享与碰撞。其二,我觉得我针对这个话题,可以半个小时之内搞定,争取在 1 点前关灯睡觉,哈哈。 现在,我们来一起探讨 API 的设计之道。我会抛出几个观点,欢迎探讨。 一、定义好的规范,已经成功了一大半 通常情况下,规范就是大家约定俗成的标准,如果大家都遵守这套标准,那么自然沟通成本大大降低。例如,大家都希望从阿里的规范上面学习,在自己的业务中也定义几个领域模型:VO、BO、DO、DTO。其中,DO(Data Object)与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。 而 DTO(Data Transfer Object)是远程调用对象,它是 RPC 服务...
- 下一篇
LINUX之Bash-Script
最近把Linux Bash编程的知识复习了一遍,大概梳理了一下,做个记录。 第一个Bash-Script LINUX shell的种类非常之多,但是目前用得最为广泛的还是Bash,本文也是基于Bash的Shell环境。 下面是一个简单的示例: #! /bin/sh echo 'hello world!' 这就是一个最简单的shell脚本了。 第一行的#!用来告诉系统,这个脚本用什么解释器来执行(说明:sh和bash本身是不同的Shell,但是在我目前用得CentOS7版本sh和bash是等价的,sh是一个指向bash的符号链接)。 echo命令输出文本到屏幕 如何运行脚本 一种方式就是将脚本作为解释器的参数,如: sh test.sh 第二种方式就是授予文件可执行权限 chmod +x test.sh 或者 chmod 755 test.sh 执行脚本 ./test.sh 变量与参数 变量 Bash是一种弱类型的语言,你只需要直接定义变量名=value即可。当需要引用这个变量的时候使用$var_name或者${var_name}即可。 $var_name是${var_name}的一种简...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题