ik分词与match_phrase短语匹配

栏目: 编程工具 · 发布时间: 6年前

内容简介:这两天遇到一个后台的检索需求,要求实现SQL中like “%xxxx%”的匹配效果。这种效果在ES中最匹配的做法是用效果最差的做法是用match全文检索,这种情况只要query分词的任何一个term出现在倒排中,就会召回文档,所以很容易搜出一些八竿子打不着的文档。

这两天遇到一个后台的检索需求,要求实现 SQL 中like “%xxxx%”的匹配效果。

wildcard通配

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

match全文匹配

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

match_phrase短语匹配

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

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

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

[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_smart',
                'text' => '青岛上合蓝',
            ]
]

得到结果:

{
	"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搜索词是:”上合蓝”,分词结果如下:

{
	"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搜索”青岛蓝”,那么”青岛”与”蓝”中间少了一个”上合”,所以无法召回:

{
	"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分词:

[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_max_word',
                'text' => '青岛上合蓝',
            ]
]

得到:

{
	"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:

[
            'index' => 'article',
            'body' => [
                'analyzer' => 'ik_max_word',
                'text' => '青岛',
            ]
]

分词结果:

{
	"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。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

3D打印

3D打印

[美]胡迪•利普森,梅尔芭•库曼 / 赛迪研究院专家组 / 中信出版社 / 2013-4 / 49.00元

《3D打印:从想象到现实》内容简介:你需要一把功能强大的锤子?你需要一双精致无比的鞋子?你需要给孩子准备奇异的玩具?你需要一顿精美的晚餐?只管打印出来就行了。《3D打印:从想象到现实》带你走进3D打印的世界,认识一下当下这个最酷的东西——它将从想象变成现实,并带来一场深刻的社会革命。 书中讲述了3D打印技术的突破性发展,以及3D打印技术将如何应用在学校、厨房、医院等场所的。《3D打印:从想象......一起来看看 《3D打印》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具