昨天有一个需求,就是想要根据某个网关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. js闭包 选择器 面向对象 事件 操作页面

    闭包js函数的嵌套定义,定义在内部的函数 就称之为闭包为什么使用闭包: 1.一个函数要使用另一个函数的局部变量 2.闭包会持久化包裹自身的函数的局部变量 3.解决循环绑定 function outer ...

  2. BZOJ 1083 [SCOI2005]繁忙的都市 (最小生成树裸题无重边) 超简单写法!!

    Description 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口 ...

  3. 单交换机划分VLAN配置

    实验要求:相同vlan的主机能够通信,不同vlan的主机不能通讯 拓扑如下: 涉及内容有: 1.端口trunk模式设置 2.VTP的创建和设置 3.vlan的划分 配置如下: A enable 进入特 ...

  4. NEO VM原理及其实现(转载)

    NEO Vm原理及其实现 简介及与evm主要区别 neo vm和evm类似.底层都实现了一套opcode以及对应的执行器,opcode设计差距蛮大的,总体上来说evm的更加简洁,neo vm的功能更加 ...

  5. Ubuntu16.04安装&创建虚拟环境

    一.linux环境 Ubuntu16.04 二.安装和配置虚拟环境 安装虚拟环境 sudo pip install virtualenv sudo pip install virtualenvwrap ...

  6. Python学习笔记第五周

    目录 一.基础概念 1.模块定义 2.包的定义 3.导入包的本质 4.导入模块的本质 5.导入方法 6.import的本质 7.导入优化 8.模块分类 9.标准库介绍 1.time与datetime ...

  7. zedboard开发板上移植opencv代码(立体匹配)

    前言 公司要做立体匹配相关的项目,已有matlab和c++版本,可是不能做到实时显示立体信息,想要硬件实现实时,无奈本渣也是个硬件的新手,先按照实验室lyq同学的思路在zedboard开发板的纯ARM ...

  8. 将js和css文件装入localStorage加速程序执行

    原理如下: 一次批量加要加载的文件存入数组,采用Ajax方式异步载入各个文件,然后采用循环方式逐个执行下载下来的Js或者Css文件,如果已经被缓存(localStorage)的则省略下载过程. 由于J ...

  9. [LeetCode&Python] Problem 520. Detect Capital

    Given a word, you need to judge whether the usage of capitals in it is right or not. We define the u ...

  10. 陕西师范第七届I题----排队

    链接:https://www.nowcoder.com/acm/contest/121/I来源:牛客网 题目描述 ACM竞赛队内要开运动会啦!!!! 竞赛队内的一群阳光乐观积极的队员们迅速的在操场上站 ...