前言
es作为一个搜索引擎,强大的搜索功能一定是少不了的,当使用ELK将日志打入es中国呢,如何通过关键词来对日志定位呢?所以基本的查询语句还是要了解的,先解燃眉之急。
DSL
DSL对SE的意义就像SQL对MySQL一样,学会如何编写查询语句决定了后期是否能完全驾驭ES,所以至关重要,记下来我们先简单的了解一下(毕竟我也只会这么多)
我们先针对于大量的使用场景来讲,我们更多的使用的都是查询功能,所以DSL通常都是下面结构开头,意为查询功能
GET elk-2020.08.28/_search
{"query" : {}
}
开头的GET
指的是Get请求, elk-2020.08.28
是我定义索引的名称,_search
为查询方法,其顺序为
GET index_name/type_name/_search
请求方法 索引 类型 查询
但是es7.X版本之后,为了提高效率。每个索引只有一个type,所以就可以省略
GET index_name/_search
GET index_name/_doc/_search
上面一个意思,type默认名称为_doc,所以省略和加上查出结果相同
我们首先模拟一下SQL最常用到的一条 select * from table_name
GET elk-2020.08.28/_search
{"query" : {
"match_all": {}
}
}
如果只需要查询到部分字段,不需要全部查出来,下面即只查出message和info信息
GET elk-2020.08.28/_search
{"query" : {
"match_all": {}
},
"_source": ["message","info"]
}
接下来讲有条件查询的方式,主要分为trem 和 match
GET elk-2020.08.28/_search
{"query" : {
"term": {
"title": "exception"
}
}
}
-------------------------------------------------------------------
GET elk-2020.08.28/_search
{"query" : {
"match" : {
"title": "throw exception"
}
}
}
term可以理解为精确查询,不会在根据查询的内容进行分词,及查询title中包含‘exception‘的document
而match不同的是,在查询之前,会先将索引条件’throw exception‘进行分词,分为‘throw’和 ‘exception‘两个,索引会查询出分别命中‘throw’和 ‘exception‘的document。
那term能不能match一样多命中呢?
可以使用terms来进行查询,使用[ ]
讲每个检索的单词分开,即可对指定索引多命中检索。
GET elk-2020.08.28/_search
{"query" : {
"terms": {
"title": ["exception","threw"]
}
}
}
同理,当出现一个词组‘threw exception’时,那match能不能term实现单一命中,而而不进行分词?
可以使用match_phrase来进行查询,即可对指定索引单一命中检索。
GET elk-2020.08.28/_search
{"query" : {
"match_phrase": {
"title": "threw exception"
}
}
}
上面命中规则大致相当于SQL中的=
,因为es底层使用的倒排索引,不知道排索引的可移步至「倒排索引」,倒排索引将每个检索文本进行拆分为一个或多个term,然后查询的时候分别命中,然而在命中的过程中还是使用=
规则来进行命中。
那如何实现SQL中like操作呢?
这里我们学一下下es的模糊查询,模糊查询简单分为前缀查询、正则查询和通配符查询三种
前缀查询
顾名思义,前缀查询就类似于SQL的like ’text%‘ 百分号在后面的模糊匹配,查出th
开头document
GET elk-2020.08.28/_search
{ "query": {
"prefix" : {
"title" : { "value" : "th"} }
}
}
正则查询
通过正则模糊查询出匹配的ducument
GET elk-2020.08.28/_search
{
"query": {
"regexp": {
"message": "th.*w"
}
}
}
通配符
使用通配符是 “*”,它匹配任何字符序列(包括空字符);还有 “?”,它匹配任何单个字符,来模糊匹配符合的document
GET elk-2020.08.28/_search
{
"query": {
"wildcard": {
"message": "*ption*"
}
}
}
RG:模糊查询数据量越大效率越低,当查询内容较多,数据量较大时建议将该字段设置成text进行分词,然后通过match进行匹配。
现在思考一下多条件查询呢?如何实现SQLand
和or
的多条件查询?
在es中and
对应的关键字为 must, or
对应的关键字为 should
下面就是must查询,查询出message 匹配‘exception’ 并且(and) info匹配‘error‘的document
GET elk-2020.08.28/_search
{
"query": {
"bool": {
"must":{
"term":{
"message": "exception",
"info":"error"
}
}
}
}
}
接下来是should查询,查询出message 匹配‘exception’ 或者(or) info匹配‘error‘的document,可以注意到,should是多条件,所以在should中是用[]
来将多条件分隔开
GET elk-2020.08.28/_search
{
"query": {
"bool": {
"should":[
{"term":{
"message": "exception"
}
},
{"term":{
"info": "error"
}
}
]
}
}
}
查询排序
接下来我们进行排序操作,使用sort关键字,同SQL一样,排序放在最后面,并支持多个字段排序
GET elk-2020.08.28/_search
{ "query": {
"term" : {
"message" : { "value" : "exception"}
}
},
"sort": [{
"age": {
"order": "desc"
}
},
{
"name": {
"order": "asc"
}
}
]
}
范围查询
再回到范围查询,使用range关键字。范围查询于SQL不太一样,使用的不是符号,而像Mongo一样使用gte(>=) 、 lte(<=)、gt(>)、lt(<)
GET elk-2020.08.28/_search
{
"query": {
"range" : {
"brithday" : {
"gte": "01/01/2012",
"lte": "2013",
"format": "dd/MM/yyyy||yyyy"
}
}
}
}