ElasticSearch term和match查询机制解析和隐藏的查询问题
2. 关于默认分析使用term查询的问题
之前说过es的默认分析器会讲中文拆分成一个个的单个汉子,搜索条件“内科”会被分析为“内”和“科”,从而进行搜索。而对于搜索我们常用的match搜索类似于数据库的模糊查询,term搜索为精确查询。使用的时候会出现以下情况:
2.1 场景
默认不对索引下的字段进行mapping操作时,使用的是默认分析器,假设有如下数据内容:
内科
内一科
内二科
普通内科
肿瘤内科
我们使用match搜索来搜索“肿瘤”,得到的结果显而易见是“肿瘤内科”,搜索“肿瘤内科”,得到的不仅是“肿瘤内科”,“内一科”等另外几个包含“内”、“科”的也会列出来,但是当我们使用term搜索“肿瘤”时,我们得到的是空的结果,这也是显而易见的,因为term是精确查询,“肿瘤”和“肿瘤内科”是不同的。那么如果我们term搜索“肿瘤内科”,理论上应该出现“肿瘤内科”才符合我们的预期。但是:
{"query":{"term":{"name":"肿瘤内科"}}
}
<----------- result ----------->
{"took": 1,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 0,"max_score": null,"hits": []}
}
得到的结果依然是空的,我们更换搜索条件,输入“内科”,得到的依然是空的。但是当我们输入“肿”或者“肿瘤内科”的任意一个单字时,都可以的到“肿瘤内科”的结果,于此同时,“内”和“科”将会得到所有包含“内”和“科”字的数据。
2.2 分析原因
原因在上一节内容里已经提及,默认的分析器会讲中文分析称单个字,不会有任何联字,也就是说,4个字的“肿瘤内科”倒排索引是“肿“、”瘤“、”内“、”科”,使用term查询时,必须是以上四个单字中的某一个才行。那么这时候是不是和之前提到的搜索条件也需要进行对应的分析,根据分析的倒排索引就行查询相矛盾?这里我们需要先明白match查询和term查询的机制。
2.2.1 match查询的原理
- 检查字段类型 。
name 字段是一个 string 类型( analyzed )已分析的全文字段,这意味着查询字符串本身也应该被分析。这里的“肿瘤内科”会被分析为“肿“、”瘤“、”内“、”科” - 分析查询字符串 。
将查询的字符串 “肿瘤内科” 传入标准分析器中,输出的结果是单个项 。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询。在这里也就是会将“肿“、”瘤“、”内“、”科”四个单字分别进行term查询 - 查找匹配文档 。
用 term 查询在倒排索引中查找 “肿“、”瘤“、”内“、”科” 然后获取一组包含该项的文档,本例的结果是文档:“内科”,“内一科”,“内二科”,“普通内科”,“肿瘤内科”,“内科”。 - 为每个文档评分 。
用 term 查询计算每个文档相关度评分 _score ,这是种将 词频(term frequency,即 “肿“、”瘤“、”内“、”科” 在相关文档的 name 字段中出现的频率)和反向文档频率(inverse document frequency,即词 “肿“、”瘤“、”内“、”科” 在所有文档的 name 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。
2.2.2 term查询原理
首先需要注意的一点是,term查询是非评分查询,而match是评分查询,其次,term查询时,不会进行分词,而match查询前会跟去盖子段已经配置好的分析器进行相应的分析。其查询内部的操作为:
查找匹配文档.
term 查询在倒排索引中查找 “肿瘤内科” 然后获取包含该 term 的所有文档。本例中,显然没有符合的。切记index内的“肿瘤内科”并不是以直接的“肿瘤内科”存在,而是以“肿“、”瘤“、”内“、”科”四个单字存在。
- 创建 bitset.
过滤器会创建一个 bitset (一个包含 0 和 1 的数组),它描述了哪个文档会包含该 term 。匹配文档的标志位是 1 。本例中,bitset 的值为 [0,0,0,0,0] 。在内部,它表示成一个 “roaring bitmap”,可以同时对稀疏或密集的集合进行高效编码。 - 迭代 bitset(s)
一旦为每个查询生成了 bitsets ,Elasticsearch 就会循环迭代 bitsets 从而找到满足所有过滤条件的匹配文档的集合。执行顺序是启发式的,但一般来说先迭代稀疏的 bitset (因为它可以排除掉大量的文档)。 - 增量使用计数
Elasticsearch 能够缓存非评分查询从而获取更快的访问,但是它也会不太聪明地缓存一些使用极少的东西。非评分计算因为倒排索引已经足够快了,所以我们只想缓存那些我们 知道 在将来会被再次使用的查询,以避免资源的浪费。
所以这就解释了为什么使用term查询“肿瘤内科”,得不到“肿瘤内科”的额,而使用单子却能搜索到的问题了。
2.3 解决方式
通过对默认分析器的解读,其实无论是用默认的还是自行设置shingle等方式,对于汉子的term查询,没有一个标准的方式,使用shingle配置时,可以满足term搜索“肿瘤内科”得到“肿瘤内科”的结果,但是使用“瘤内科”,也会搜索到“肿瘤内科”,同样“内”也是,这取决于与在创建索引时的mapping中shingle最长度和最大长度的设置。所以,对于文本的搜索,term查询并非像mysql中的=一样。但是对于非文本类型,如bool和数字类型,或者大于小于等比较操作,使用term会非常的精准。
ElasticSearch term和match查询机制解析和隐藏的查询问题相关推荐
- java mysql 多表查询_解析Mysql多表查询的实现
查询是数据库的核心,下面就为您介绍Mysql多表查询时如何实现的,如果您在Mysql多表查询方面遇到过问题,不妨一看. Mysql多表查询: CREATE TABLE IF NOT EXISTS co ...
- mysql教程多表查询_解析Mysql多表查询的实现
查询是数据库的核心,下面就为您介绍Mysql多表查询时如何实现的,如果您在Mysql多表查询方面遇到过问题,不妨一看. Mysql多表查询: CREATE TABLE IF NOT EXISTS co ...
- elasticsearch7常见查询(term、match、bool、filter)
一.精准查询term term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇 1.term单值 字段只有一个值时候,用term关键词查询 查询biz_id值为190919002390 ...
- 【Elasticsearch教程18】Mapping字段类型之text 以及term、match和analyzer
Elasticsearch Mapping字段类型之text 以及term.match和analyzer 一.text场景 二.`term`查询 三.`match`查询 1. `亚瑟王`如何存储? 2 ...
- Elasticsearch教程(28) text和keyword区别 term和match区别 ik中文分词器使用
text和keyword区别 term和match区别 ik中文分词器使用 一.前言 二.之前相关的博客 三.造点测试数据 1. 创建一个index 2. 插入测试数据 四.做一份试卷 第1题:tit ...
- elasticsearch中term与match
分词器.字符串类型.倒排索引 在说term和match之前,需要先了解一下这三个概念 分词器 es默认的分词器是standard analyzer,该分词器的特点是:将所有英文字符串的大写字母转换成小 ...
- elasticsearh中查询类型,term、match、match_all、multi_match、range、bool、boosting等
查询方式有如下几种: GET /<index>/_search GET /_search POST /<index>/_search POST /_search 一般分为如下几 ...
- java操作es聚合操作并显示其他字段_java使用elasticsearch分组进行聚合查询过程解析...
这篇文章主要介绍了java使用elasticsearch分组进行聚合查询过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java连接elas ...
- ElasticSearch查询 第四篇:匹配查询(Match)
<ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...
最新文章
- Cocos2d之Action类详解
- 基于SAAS模式的报销管理系统!
- 连贯的学习黑树(插入节点)
- 近视手术─医学界的一个阴谋? !
- c语言查看进程模块,计算机二级考试C语言辅导:进程模块查看
- python实现决策树数据直接赋值导入_Python3.0 实现决策树算法的流程
- dw如何制作图片自动切换效果_什么是3D虚拟展厅,虚拟展厅如何在线3D漫游!
- flex white-space: nowrap,撑大盒子问题
- Ubuntu Qt 编译问题
- 自动Shader优化器glsl_optimizer的编译与使用
- linux weblogic java_options_使用Linux脚本更新Weblogic部署的应用程序
- BootStrap-
- Studio启动的时候报错 Could not install Gradle distribution from
- 物理内存充足,但是为什么用代码总申请不到内存呢?
- double write buffer
- Linux 下文件IO编程进程控制实验
- 基于GD库的php验证码类(支持中英文字体、背景、干扰点线、扭曲…….)
- CMT 注册——Google Scholar Id,Semantic Scholar Id,和 DBLP Id
- 云服务器只能显示控制台吗,云服务器控制台使用方法
- DelphiXE7操作sqlite数据库