ES查询之刨根问底
昨天有一个需求,就是想要根据某个网关url做过滤,获取其下面所有的上下文nginx日志;如果直接"query":"https://XXX/YYY/ZZZ"发现有问题,啥也查不出来,后来仁杰指出来需要使用“”括起来,果然这样就变成了前后匹配的模糊查询了。但是继续,我发现如果我指定了字段"query":"request:\"http://XXX/YYY/ZZZ\""就啥也返回不了了;但是如果是换位message字段则可以;后来发现原来是因为request的类型是keywords,message的类型是text,所以request必须是全匹配,message是模糊匹配。
第一部 分词
但是为什么需要添加“https://XXX/YY/ZZZ/”双引号呢?如果不添加会怎样,导致分词吗,如果分词正常应该可以查出来啊。后来发现之所以查不出来数据,是因为当时查询的querystirng最后一位带了"/"导致的,如果把最后一位的"/"给删掉就可以查出数据了;但是这个查询是经过ES的分词的,将会被解析为XXX,/YY/以及ZZZ,所以此时查询是分词查询;如果是想要不分词,进行完整匹配(ES不进行分词),需要添加双引号。如果获知分词的过程?就是通过index/_validate/query?explain,所谓的validate-query模式来进行查询解释。
通过validate-query模式的查询,你会发现如果直接查(不指定字段),将会是所有的字段对所有的分词进行笛卡尔积的匹配;所以构建的查询语句也是十分复杂,这里你就会发现指定字段重要性了。
第二部 索引
什么是索引?引用一下我之前的一篇博文来说明:
索引扮演的角色其实并不是存储,而是“索引”,看起来有点傻,但是其实我之前一直理解索引是存储,其实从命名上可以看出来,索引其实是分片的索引,分片的字典,记录了每个分片的位置,索引范围;当需要查询的时候,可以定位到对应的分片来进行数据操作;最后进行汇总。所以index本质作用就是记录分片;所谓查询,有向无环图(DAG)都是基于index来进行分析绘制的,然后基于该图下放数据操作。
索引模板,就是指定了索引的属性,包括分片数,副本数等物理属性以及字段名称以及字段类型等信息。索引模板指定了索引模式,一般都是前缀模式,例如:app_log-*,这样每当创建了一个app_log-开头的索引(比如app_log-2019-3-3),就会按照该模板的属性进行创建。
下面说一下索引的生命周期,这里包括热盘到冷盘,热盘到冷盘可以通过box_type来实现,创建的时候,指定分布部署的节点的类型(需要事先为每个集群节点设置节点类型),定时通过修改配置来对分片进行迁移到另外节点类型;
生命周期的最后操作是:删除,关闭以及归档三种,删除就是DELETE指令,关闭就是_close,这个除了会占用硬盘空间之外不会有别的影响,好处就是可以随时打开参与查询;最后一个是归档,可以将索引归档到S3,hdfs等存储引擎。这些归档文件将会被ES系统记录;此时可以将索引删除(导致分片一起删除);日后如果有需要可以通过_restore的api进行重新导入。
第三部 查询和解析
字段配置中有一个属性:index,默认是“analyzed”,代表存入文档后,将会被分词保存,同时统一转化为小写;另外一个值是not_analyzed,这样的文档里面保存的就是原始的文档内容。是的,所有的这一切都是5.0之前的配置,5.0之后,string+analyzed被text替换,string+not_analyzed被keyword替换,完美。
term查询
代表完全匹配,什么是完全匹配,是指索引保存的分词中的一个能够完全一致,和分词中的一个完全一样(不是模糊匹配);term查询不会对查询字符串进行分词;这里牵涉到term查询中指定的字段类型是keyword还是text,如果是keyword,那么分词只有一个,就是文档全文本身,此时可以理解为有的字段,在查询字符串必须要和文档全部一致才可以;如果是text,那么将会根据内置规则进行分词,此时term查询的匹配就是要能够匹配分词后的一个即可;
match查询
match查询则是会对查询字符串进行分词,然后和索引的字段分词进行逐个匹配(又是一个笛卡尔积)。所以,你会发现其实ES查询本质面对的分词,文档其实只是一个PUT的概念,一旦存入了ES之后,就会被进行分解为分词(除非keyword,唯一的分词是文档本身)。下一个是match_phase,这个查询和match一样都是解析分词查询,但是增加了所有分词必须都匹配,而且分词的顺序要一致(可以指定距离slop)。
query_string查询
那么match和query_string的差别在哪里?在于后者有谓词表达式。其实如果是没有谓词表达式,那么query_string就是和match一样,如果没有谓词,查询字段用双引号包裹,其实就和match_phrase是一样的,query_string的强大就在于一个查询可以完成match和match_phrase的统一,同时还额外提供了谓词表达式做多条件匹配。
第四部 文档写入ES流程
逐个流程可以被进一步细化:PUT了一个文档之后,首先将会进行字段级别处理,一般是在logstash中进行,对于文档中的字段通过正则等规则进行提取,提取的目的是填充到各个字段;然后对于各个字段里面保存的内容,其实是所提取出来的子文档的分词,是的,字段保存的是分词,不再内容或者子内容,而是分词。文档的概念也不是原始的字符串,而是所有的字段以及字段分词的抽象;那么查询的时候其实都是基于对于查询字符串的分词(可能是不解析,比如使用“”,那就是一个分词)和字段分词(可能是keyword,那么就只有一个分词)进行匹配;查询字符串的解析有良心的使用者指定一下字段,没良心的不指定,那么就是所有的查询分词和所有的字段分词进行笛卡尔积形式的匹配,如果匹配的上,那么该分词所在的文档就被返回。
第五部 总结和其他
索引里面存的分片信息;分片里面的存的是文档信息,文档里面存的字段信息,字段里面存的是分词信息。基本就是这么个层级关系;为什么要指定这么多层,就是为了能够细粒度定位数据,减少查询的面积。
_all字段是一个虚拟字段,它将会打破字段这个层级,将所有的字段的分词都集成到一起,形成一个新的虚拟字段:_all。设置_all是一个字段级别的设置,在每个字段下面设置_all是否可用,因为会损耗性能,所以默认是关闭。但是_all在6.0之后将会被废弃,类似功能由copy_to参数来实现。
ES查询之刨根问底的更多相关文章
- ElasticSearch 学习记录之ES查询添加排序字段和使用missing或existing字段查询
ES添加排序 在默认的情况下,ES 是根据文档的得分score来进行文档额排序的.但是自己可以根据自己的针对一些字段进行排序.就像下面的查询脚本一样.下面的这个查询是根据productid这个值进行排 ...
- .NetCore下ES查询驱动 PlainElastic .Net 升级官方驱动 Elasticsearch .Net
1.背景 由于历史原因,笔者所在的公司原有的ES查询驱动采用的是 PlainElastic.Net, 经过询问原来是之前PlainElastic.Net在园子里文档较多,上手比较容易,所以最初作者选用 ...
- Es查询工具使用
Kibana按照索引过滤数据 1.创建索引模式 2.查询索引中的数据 Es查询不返回数据 创建索引的时候指定mapping mappings={ "mappings": { &qu ...
- ES查询语句
记录常用的es 查询 聚合 GET _cat / indices GET / p_ext_develop / _mapping / g GET / p_ext_develop / _analyze { ...
- Es查询结果集默认是10000,更新设置
Es查询结果集默认是10000,结果集大小是int,最大为21亿左右 PUT _all/_settings?preserve_existing=true { "index.max_resul ...
- es 查询更新操作
# es 查询更新操作# _*_ coding: utf-8 _*_ import time import datetime import pymysql from elasticsearch imp ...
- ES查询区分大小写
ES查询区分大小写 ES查询在默认的情况下是不区分大小写的,在5.0版本之后将string类型拆分成两种新的数据类型,text用于全文搜索(模糊搜索),keyword用于关键字搜索(精确搜索). 注意 ...
- es查询命令备份(只需要网页9200/_plugin/head/就可以访问)
本文只是写一些常用es命令,这里不用任何客户端,只用 9200/_plugin/head/ 那个端口网页就可以,然后是复合查询. 注意es其实一个idnex只能有一个type,如果一个index做了多 ...
- ES查询-match VS match_phrase
我们以一个查询的示例开始,我们在student这个type中存储了一些学生的基本信息,我们分别使用match和match_phrase进行查询. 首先,使用match进行检索,关键字是“He is”: ...
随机推荐
- leetcode第40题:组合总和II
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...
- Strict Standards: Declaration of UserModel::toJSON() should be compatible with that of BaseModel::toJSON()
使用php报了这个错误: 错误的意思是: 严格标准: usermodel中的 toJSON() 方法 应该 同 BaseModel中的toJson() 方法是兼容的. php要求 子类的方法如果同父 ...
- PCMU G.711U/PCMA G.711A简介
PCMA(G.711A) 类型:Audio 制定者:ITU-T 所需频宽:64Kbps(90.4) 特性:PCMU和PCMA都能提供较好的语音质量,但是它们占用的带宽较高,需要64kbps. 优点:语 ...
- OneinStack 安装
安装步骤 注意 如果有单独数据盘,建议您先挂载数据盘,建议将网站内容.数据库放在数据盘中.如何挂载数据盘,请参考(支持阿里云.腾讯云):<如何利用脚本自动化挂载数据盘?> yum -y i ...
- wx小程序用canvas生成图片流程与注意事项
1.需要画入canvas的 图片都需要先缓存到本地 let ps = [] ps.push(that.loadImageFun(this.statusInfo.avatar_url, "he ...
- 鼠标滑过元素,div显示,并根据scrollTop向下移动
如上图所示,通道有很多个,表格只有一个. 注意:滑过通道时鼠标如果停留在上面,那么表格才显示,鼠标滑过表格时,表格不消失 <div id="lineContent"> ...
- 【转】在python3.5安装tkinter
链接:https://www.zhihu.com/question/42162071/answer/95441732 安装tkinter tkinter是由tcl和tk两个部分组成的,所以下载tkin ...
- python代理可用检测、代理类型检测
#coding:utf-8 import urllib2 def url_user_agent(proxy,url): proxy_support = urllib2.ProxyHandler({'h ...
- 2017-2018-2 20165228 实验四《Android程序设计》实验报告
一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:苏祚堃 学号:20165228 指导教师:娄嘉鹏 实验日期:2018年5月14日 实验时间:13:45 - 3:25 实验序号:实验四 ...
- PHP 设计模式系列 —— 工厂方法模式(Factory Method)(转)
1.模式定义 定义一个创建对象的接口,但是让子类去实例化具体类.工厂方法模式让类的实例化延迟到子类中. 2.问题引出 框架需要为多个应用提供标准化的架构模型,同时也要允许独立应用定义自己的域对象并对其 ...