Elasticsearch Query DSL查询入门

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中可以通过以下几种方法来指定索引

  1. 指定一个固定的索引,ops-coffee-nginx-2019.05.15为索引名字
GET /ops-coffee-nginx-2019.05.15/_search

以上表示在ops-coffee-nginx-2019.05.15索引下查找数据

  1. 指定多个固定索引,多个索引名字用逗号分割
GET /ops-coffee-nginx-2019.05.15,ops-coffee-nginx-2019.05.14/_search
  1. 用*号匹配,在匹配到的所有索引下查找数据
GET /ops-coffee-nginx-*/_search

当然这里也可以用逗号分割多个匹配索引

分页查询

上边有说到查询结果hits默认只展示10个文档,那我们如何查询10个以后的文档呢?ES中给了sizefrom两个参数

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

最简单的查询,下边的例子就表示查找hostops-coffee.cn的所有记录

GET /ops-coffee-2019.05.15/_search
{
  "query":{
    "match": {
      "host":"ops-coffee.cn"
    }
  }
}

multi_match

在多个字段上执行相同的match查询,下边的例子就表示查询hosthttp_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小于等于

当使用日期作为范围查询时,我们需要注意下日期的格式,官方支持的日期格式主要有两种

  1. 时间戳,注意是毫秒粒度
GET /ops-coffee-2019.05.14/_search
{
  "query": {
    "range": {
      "@timestamp": {
        "gte": 1557676800000,
        "lte": 1557680400000,
        "format":"epoch_millis"
      }
    }
  }
}
  1. 日期字符串
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来实现了

例如我们要查询hostops-coffee.cnhttp_x_forworded_for111.18.78.128status不为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

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/8247

(0)
杰斯的头像杰斯
上一篇 2023年5月26日 下午5:16
下一篇 2023年5月29日 下午5:21

相关推荐

  • 解决远程连接MySQL报错:2003 – Can‘t connect to MySQL server on ‘X.X.X.X‘ (10060 “Unknown error“)问题

    问题先看报错: 2003 – Can’t connect to MySQL server on ‘X.X.X’ (10060 “Unknown error”)。 意思是服务器远程连接出错:未知错误。 解决方案:遇到这个问题,首先想到的是权限不够。那咱就给它赋权。 首先登录MySQL数据库:mysql -u用户名 -p密码; 然后:use mysq…

    2023年7月27日
    29100
  • Oracle报错:ORA-00257 错误处理

    一、错误描述 使用plsql develop工具登录数据库时,有如下报错: ORA-00257:archiver error. Connect internal only. unitl freed. 二、错误原因 archive log 日志已满 三、处理方法 1.用sys用户登录 2.查看archivlog所在位置 3.VALUE为空时,可用archive…

    2023年3月25日
    21000
  • 如何解决生产环境MySQL的死锁问题

    生产问题 在生产环境中发现我们数据库出现了一个异常,异常堆栈信息如下: 从堆栈信息可以很容易知道死锁问题。但是这个更新语句为什么会出现死锁呢? 问题原因 死锁产生的原因有四个分别是: 互斥 循环等待 不可剥夺 请求与保持 只要产生死锁以上四个条件比然满足,因此考虑这个SQL语句是否产生了这四个死锁条件。 分析: 由于我们使用的是云数据库,因此可以通过云数据库…

    2022年8月21日
    57400
  • mysql的主从延迟问题主要原因及解决

    MySQL数据库主从的安装搭建方法 在实际的生产中,为了解决Mysql的单点故障已经提高MySQL的整体服务性能,一般都会采用主从复制。 比如:在复杂的业务系统中,有一句sql执行后导致锁表,并且这条sql的的执行时间有比较长,那么此sql执行的期间导致服务不可用,这样就会严重影响用户的体验度。 主从复制中分为主服务器(master)和从服务器(slave)…

    2022年6月14日
    84900
  • 【mySQL】left join、right join和join的区别

    首先,我们先来建两张表,第一张表命名为kemu,第二张表命名为score: 一、left join顾名思义,就是“左连接”,表1左连接表2,以左为主,表示以表1为主,关联上表2的数据,查出来的结果显示左边的所有数据,然后右边显示的是和左边有交集部分的数据。如下: 结果集: 二、right join “右连接”,表1右连接表2,以右为主,表示以表2为主,关联查…

    2023年8月29日
    23100

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信