昨天有一个需求,就是想要根据某个网关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查询之刨根问底的更多相关文章

  1. ElasticSearch 学习记录之ES查询添加排序字段和使用missing或existing字段查询

    ES添加排序 在默认的情况下,ES 是根据文档的得分score来进行文档额排序的.但是自己可以根据自己的针对一些字段进行排序.就像下面的查询脚本一样.下面的这个查询是根据productid这个值进行排 ...

  2. .NetCore下ES查询驱动 PlainElastic .Net 升级官方驱动 Elasticsearch .Net

    1.背景 由于历史原因,笔者所在的公司原有的ES查询驱动采用的是 PlainElastic.Net, 经过询问原来是之前PlainElastic.Net在园子里文档较多,上手比较容易,所以最初作者选用 ...

  3. Es查询工具使用

    Kibana按照索引过滤数据 1.创建索引模式 2.查询索引中的数据 Es查询不返回数据 创建索引的时候指定mapping mappings={ "mappings": { &qu ...

  4. ES查询语句

    记录常用的es 查询 聚合 GET _cat / indices GET / p_ext_develop / _mapping / g GET / p_ext_develop / _analyze { ...

  5. Es查询结果集默认是10000,更新设置

    Es查询结果集默认是10000,结果集大小是int,最大为21亿左右 PUT _all/_settings?preserve_existing=true { "index.max_resul ...

  6. es 查询更新操作

    # es 查询更新操作# _*_ coding: utf-8 _*_ import time import datetime import pymysql from elasticsearch imp ...

  7. ES查询区分大小写

    ES查询区分大小写 ES查询在默认的情况下是不区分大小写的,在5.0版本之后将string类型拆分成两种新的数据类型,text用于全文搜索(模糊搜索),keyword用于关键字搜索(精确搜索). 注意 ...

  8. es查询命令备份(只需要网页9200/_plugin/head/就可以访问)

    本文只是写一些常用es命令,这里不用任何客户端,只用 9200/_plugin/head/ 那个端口网页就可以,然后是复合查询. 注意es其实一个idnex只能有一个type,如果一个index做了多 ...

  9. ES查询-match VS match_phrase

    我们以一个查询的示例开始,我们在student这个type中存储了一些学生的基本信息,我们分别使用match和match_phrase进行查询. 首先,使用match进行检索,关键字是“He is”: ...

随机推荐

  1. TensorFlow函数:tf.zeros_like

    tf.zeros_like函数 tf.zeros_like( tensor, dtype=None, name=None, optimize=True ) 定义在:tensorflow/python/ ...

  2. kbmMW 5.08.10试用报告

    1.不兼容Android 基于5.07的项目,升级到5.08,不能编译android app.已经反应给作者.作者回复将近快发布fixed,修正这个问题及其他发现的问题. 5.08.01解决了andr ...

  3. Java学习笔记11(this,super)

    this在构造方法间的使用, public class Person { private String name; private int age; public Person() { //this( ...

  4. JAVA自动补全代码

    打开eclipse(对myeclipse同样适用) 找到窗口(windows)菜单,打开最后一项首选项(Preferences)找到下属菜单java打开,打开里边的编辑器(Editor)菜单,点击内容 ...

  5. vuejs中v-bind绑定class时的注意事项

    关于v-bind绑定class的实例 作用:可用于不同样式之间的切换 <!DOCTYPE html> <html lang="en"> <head&g ...

  6. async/await学习笔记

    async/await 的目的是简化使用 promises 的写法.     让我们来看看下面的例子: // 一个标准的 JavaScript 函数 function getNumber1() { r ...

  7. 第三十二课 linux内核链表剖析

    __builtin_prefetch是gcc扩展的,用来提高访问效率,需要硬件的支持. 在标准C语言中是不允许static inline联合使用的. 删除依赖的头文件,将相应的结构拷贝到LinuxLi ...

  8. grep命令相关用法

    grep命令相关参数: -i:忽略大小写 --color:高亮显示匹配到的信息 -v:反向查找,没匹配到的行显示出来 -o:只显示被模式匹配到的串本身 正则表达式: .*:任意长度的任意字符,贪婪模式 ...

  9. 查询表Or列的注释信息

    需求:开发人员需要DBA支持,查询表的注释说明,用于明确表的用途. 1.测试 session 1 创建测试表SQL> create table a_emp as select * from sc ...

  10. MySQL中的存储过程和函数使用详解

    一.对待存储过程和函数的态度 在实际项目中应该尽量少用存储过程和函数,理由如下: 1.移植性差,在MySQL中的存储过程移植到sqlsever上就不一定可以用了. 2.调试麻烦,在db中报一个错误和在 ...