比如:要求实现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. WinDbg安装

    WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件. 主页:http://msdn.microsoft ...

  2. 黄聪:C#中CefSharp的简单使用

    C#中CefSharp的简单使用 https://blog.csdn.net/qq_26712977/article/details/78282995

  3. 工控随笔_19_西门子_WinCC的VBS脚本_08_常量和流程控制_01

    在编程的过程中,有时候我们会使用一些固定的值,例如圆周率,或者某个人的生日,或者家庭住址等等, 这些信息对于一个对象来说一旦确定就不会改变,因此我们在编程的时候也不希望这些信息会改变,在VBS里面 也 ...

  4. C# DataTable Lamda GroupBy

    static void Main(string[] args) { DataTable dt = new DataTable(); dt.Columns.Add("A"); dt. ...

  5. centos7虚拟机克隆后设置固定IP

    虚拟机centos7克隆一份出来之后,新centos7更改了固定IP,可是不生效.重启网卡时报错: network.service: control process exited, code=exit ...

  6. 学习笔记《Java多线程编程实战指南》三

    3.1串行.并发与并行 1.串行:一件事做完接着做下一件事. 2.并发:几件事情交替进行,统筹资源. 3.并行:几件事情同时进行,齐头并进,各自运行直到结束. 多线程编程的实质就是将任务处理方式由串行 ...

  7. qnx gpio

    in order to set gpio in qnx, you can use msmgpiotool # msmgpiotool gpiotool usage: gpiotool <comm ...

  8. 【01】团饱和图:(一)EHM定理

    团饱和图:(一)EHM定理 据A. Hajnal考证,术语"饱和性",即saturation,最早由前苏联数学家A. A. Zykov在1949年引入,用于研究线性复形,但是他的工 ...

  9. 深度学习(二)--深度信念网络(DBN)

    深度学习(二)--深度信念网络(Deep Belief Network,DBN) 一.受限玻尔兹曼机(Restricted Boltzmann Machine,RBM) 在介绍深度信念网络之前需要先了 ...

  10. Linux系统的RAID磁盘阵列

    RAID概念 磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意. 磁盘阵列是由很多价格较便宜的磁盘,以硬件( ...