比如:要求实现SQL中like “%xxxx%”的匹配效果。

wildcard通配

这种效果在ES中最匹配的做法是用wildcard query通配,这种情况不会对query分词,而是直接遍历倒排索引逐个匹配计算,性能是无法想象的,大家慎用。

match全文匹配

效果最差的做法是用match全文检索,这种情况只要query分词的任何一个term出现在倒排中,就会召回文档,所以很容易搜出一些八竿子打不着的文档。

term匹配

如果你的搜索词本身不需要分词,只是一个term的话,那么直接走term query是最方便的。

match_phrase短语匹配

推荐一个折衷性能与准确度的做法就是用match_phrase短语匹配。

match_phrase的原理是对query分词,要求所有的term都出现在倒排中,并且连续且顺序一致的排列,下面一起看个例子。

我们采用ik_smart中文分词器,对”青岛上合蓝”分词:

 
1
2
3
4
5
6
7
[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_smart',
                'text' => '青岛上合蓝',
            ]
]

得到结果:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"tokens": [{
"token": "青岛",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
}, {
"token": "上合",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
}, {
"token": "蓝",
"start_offset": 4,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
}]
}

大家看到,每个term都有一个position字段标识了term的位置,这将直接影响match_phrase是否可以召回。

接着我们进行搜索,query搜索词是:”上合蓝”,分词结果如下:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"tokens": [{
"token": "上合",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
}, {
"token": "蓝",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
}]
}

“上合”与”蓝”的position紧密排列,与之前”青岛上合蓝”中的”上合”与”蓝”顺序一致且连续,所以match_phrase搜索”上合蓝”可以召回上述的”青岛上合蓝”。

相反,如果你query搜索”青岛蓝”,那么”青岛”与”蓝”中间少了一个”上合”,所以无法召回:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"tokens": [{
"token": "青岛",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
}, {
"token": "蓝",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
}]
}

所以,match_phrase的确可以解决我们的这个场景。

因为match_phrase需要分词,所以如果分词效果不好(词库不足),query就会产生不同于doc的term,如果term都不同就肯定无法匹配了。

但是大家要注意,match_phrase与ik_max_word分词器是无法一起工作的,因为ik_max_word分词的term具有重叠问题,下面举个栗子:

先用ik_max_word分词:

 
1
2
3
4
5
6
7
[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_max_word',
                'text' => '青岛上合蓝',
            ]
]

得到:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"tokens": [{
"token": "青岛",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
}, {
"token": "岛上",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
}, {
"token": "岛",
"start_offset": 1,
"end_offset": 2,
"type": "CN_WORD",
"position": 2
}, {
"token": "上合",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 3
}, {
"token": "蓝",
"start_offset": 4,
"end_offset": 5,
"type": "CN_WORD",
"position": 4
}]
}

你从”岛上”,”岛”就能看出,它的term之间具有重叠情况,这与ik_smart是完全不同的,因为ik_max_word的目标是尽可能产生更多的term组合,一般用于全文检索提高召回率。

接着我们搜索下面的query:

 
1
2
3
4
5
6
7
[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_max_word',
                'text' => '青岛',
            ]
]

分词结果:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"tokens": [{
"token": "青岛",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
}, {
"token": "岛",
"start_offset": 1,
"end_offset": 2,
"type": "CN_WORD",
"position": 1
}]
}

“青岛”与”岛”之间差着一个”岛上”,结果就是match_phrase不匹配。

最后给大家一个结论:

如果大家用match_phrase的话,需要注意2个方面:1)分词器不准会影响召回;2)只能用ik_smart。

其他对于ES 默认分词等其他分词同样适用

原文链接:https://yuerblog.cc/2018/09/13/ik-with-match_phrase

ES match match_phrase term willcard的查询原理的更多相关文章

  1. ElasticSearch match, match_phrase, term区别

    1.term结构化字段查询,匹配一个值,且输入的值不会被分词器分词. 比如查询条件是: { "query":{ "term":{ "foo" ...

  2. ES 入门记录之 match和term查询的区别

    ElasticSearch 系列文章 1 ES 入门之一 安装ElasticSearcha 2 ES 记录之如何创建一个索引映射 3 ElasticSearch 学习记录之Text keyword 两 ...

  3. es match、match_phrase、query_string和term的区别

    (一)text字段和keyword字段的区别 以下给出一个例子: 首先建立一个索引和类型,引入一个keywork的字段: PUT my_index { "mappings": { ...

  4. elasticsearch 查询(match和term)

    elasticsearch 查询(match和term) es中的查询请求有两种方式,一种是简易版的查询,另外一种是使用JSON完整的请求体,叫做结构化查询(DSL). 由于DSL查询更为直观也更为简 ...

  5. (转载)elasticsearch 查询(match和term)

    原文地址:https://www.cnblogs.com/yjf512/p/4897294.html elasticsearch 查询(match和term) es中的查询请求有两种方式,一种是简易版 ...

  6. es创建普通索引以及各种查询

    创建索引 创建普通索引: PUT /my_index { "settings": { "index": { "number_of_shards&quo ...

  7. 基于Lucene查询原理分析Elasticsearch的性能

    前言 Elasticsearch是一个很火的分布式搜索系统,提供了非常强大而且易用的查询和分析能力,包括全文索引.模糊查询.多条件组合查询.地理位置查询等等,而且具有一定的分析聚合能力.因为其查询场景 ...

  8. ES 入门 - 基于词项的查询

    准备 首先先声明下,我这里使用的 ES 版本 5.2.0. 为了便于理解,这里以如下 index 为格式,该格式是通过 PMACCT 抓取的 netflow 流量信息, 文中所涉及的到的例子,全基于此 ...

  9. Lucene 查询原理 传统二级索引方案 倒排链合并 倒排索引 跳表 位图

    提问: 1.倒排索引与传统数据库的索引相比优势? 2.在lucene中如果想做范围查找,根据上面的FST模型可以看出来,需要遍历FST找到包含这个range的一个点然后进入对应的倒排链,然后进行求并集 ...

随机推荐

  1. html5/h5课件如何制作?

    随着flash逐渐被html5取代,很多教育机构都在面临着如何将自己的flash交互课件产品转换到html5版本的问题,最近遇到非常多的客户一上来就问我,flash课件能直接转成Html5课件么?答案 ...

  2. Linux运维宝典:最常用的150个命令汇总

    一.线上查询及帮助命令(2个) 二.文件和目录操作命令(18个) 三.查看文件及内容处理命令(21个) 四.文件压缩及解压缩命令(4个) 五.信息显示命令(11个) 六.搜索文件命令(4个) 七.用户 ...

  3. 20175236 2018-2019-2 《Java程序设计》第五周学习总结

    教材学习内容总结 接口回调 1.接口属于引用型变量,可以存放实现该接口类的实例的引用,即存放对象的引用. 2.接口回调理解上跟对象的上转型对象差不多. 理解接口 接口可以抽象出重要的行为标准. 接口多 ...

  4. Preloading Your ASP.NET Applications

    You may have noticed that the first request to an ASP.NET Web site takes longer than subsequent requ ...

  5. C语言排序算法学习笔记——插入类排序

    排序就是讲原本无序的序列重新排序成有序的序列.序列里可以是一个单独数据,也可以是多个数据组合的记录,按照记录里的主关键字或者次关键字进行排序. 排序的稳定性:如果排序表中有两个元素R1,R2,其对应的 ...

  6. 问题-python3.6找不到tkinter

    问题:import tkinter失败 然后直接pip安装也不ok python3.6安装过程中会提示是否选择安装tkinter,如此只有打开原来的安装程序 勾选箭头所示

  7. 如何将composer设置为全局变量?

    全局安装是将 Composer 安装到系统环境变量 PATH 所包含的路径下面,然后就能够在命令行窗口中直接执行 composer 命令了. Mac 或 Linux 系统: 打开命令行窗口并执行如下命 ...

  8. python-封装方法用于读取excel

    1.实现获取excel某张表的行数.单元格数据 #coding=utf-8 import xlrd #获取excel文件 data = xlrd.open_workbook('file_path/xx ...

  9. Kettle通过Webservice获取天气信息

      Kettle通过Webservice获取天气信息 需求: 通过kettle工具,通过webservice获取天气信息,写成xml格式文件. 思路: Kettle可通过两种选择获取webservic ...

  10. Linux中docker的使用(2)

    容器下安装jdk和tomcat:通过挂载文件的方法,把宿主机上的文件挂载到容器中,然后解压到opt目录下:tar -zxvf 包名 -C /opt//opt目录下drwxr-xr-x 8 10 143 ...