检索类型脑图:
精准匹配检索和全文检索的本质区别
精准匹配检索和全文检索的本质区别:
- 精准匹配把检索的整个文本不做分词处理,当前一个串整体处理。
- 而全文检索需要分词处理,对分词后的每个词单独检索然后大bool组合检索。
直接用列子来看:
//mapping映射
PUT test
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
//利用bulk批量插入数据
POST test/_bulk
{"index":{"_id":1}}
{"title":"乌兰图雅经典歌曲30首连播 标清_手机乐视视频"}
{"index":{"_id":2}}
{"title":"乌兰县地区生产总值22.9亿元 "}
{"index":{"_id":3}}
{"title":"乌兰新闻网欢迎您!"}
{"index":{"_id":4}}
{"title":"乌兰:你说急什么呢,我30岁了"}
{"index":{"_id":5}}
{"title":"千城胜景丨胜境美誉 多彩乌兰"}
利用以下搜索来说明:
POST test/_search
{
"profile": true,
"query": {
"match": {
"title": "乌兰新闻网欢迎您!"
}
}
}
结果为:
为什么通过检索“乌兰新闻网欢迎您!”召回了全部数据???
我们加上"profile": true看下:
简单来说一句话:match_query 在检索的时候将待检索字符串做了分词处理。
我们可以通过analyzer API 看出:
精准匹配的检索实现:
POST test/_search
{
"profile": true,
"query": {
"term": {
"title.keyword": "乌兰新闻网欢迎您!"
}
}
}
结果:
也就是说,精准匹配是拿整个文本串一起 term query检索的,不做分词处理。
精准匹配检索
- Term单字段精准匹配
- Term query 应用场景:单值精准匹配。
- 注意点:避免将 term query 应用到 text 类型的检索。
再延伸一些,Term 检索针对的是非 text 类型,term 针对 text 类型并不会报错,但结果会达不到预期。
如果我非要将 text 类型应用 term query会怎么样?来吧,看一下效果:
DELETE my-index-000001
# 不指定分词器就使用默认:standard 分词器。
PUT my-index-000001
{
"mappings": {
"properties": {
"full_text": {
"type": "text"
}
}
}
}
# 写入数据
PUT my-index-000001/_doc/1
{
"full_text": "Quick Brown Foxes!"
}
# 执行检索,并不会召回数据
GET my-index-000001/_search?pretty
{
"profile": true,
"query": {
"term": {
"full_text": "Quick Brown Foxes!"
}
}
}
检索结果如上图所示,为啥没有召回结果数据?
原因在于:写入的时候,Quick Brown Foxes! 经过默认分词器 standard 处理后,转化为:quick、brown、foxes 存储。
- Terms 多字段精准匹配
- Terms query 应用场景:多值精准匹配。
注意点:同 term query核心区别:terms query 支持多个值,而 term query 仅支持单个值。
- Range 范围检索
- Range query 应用场景:区间范围检索。
注意点1:当“search.allow_expensive_queries”设置为 false 时,range query 在 text 和 keyword 类型的检索不能被执行。
注意点2:range query 对 text、keyword 类型的区间检索实际意义不大。
- Exists 是否存在检索
- Exists query 应用场景:判定字段是否有值。
- Wildcard 类Mysql like 检索
Wildcard 应用场景:通配符检索,类似 MySQL like 查询。
- prefix 前缀匹配检索
prefix Query应用场景:前缀匹配。
- Terms set 检索
Terms set Query 应用场景:term query 检索 1个满足条件,terms query检索多个满足条件,而 Terms set query 介于两者中间。
- Fuzzy 支持编辑距离的模糊查询
Fuzzy Query 应用场景:返回包含与搜索词相似的词的文档,也就是说:有一定的类似纠错功能。
- IDs 检索
IDS query:基于 ID 组召回数据。
- Regexp 正则匹配检索
Regexp Query:基于正则表达式的检索。
使用建议:非必要不使用。
全文检索类型
- Match 检索
- Match Query 应用场景:召回率要求高、精准度要求不高的场景。
- 使用建议:精准度要求高的场景慎用。
如前所述,Match 的本质:大 bool + term query 组合体。
- Match phrase 短语检索
- Match phrase Query 应用场景:更注重精准度召回的场景,match query 如果叫做分词检索的话,match phrase 叫短语匹配检索更为合适。
注意1:检索的时候可以指定分词器。
注意2:分词器指定不同,拼接的串中字符的切分粒度不同。
如下两个截图分别使用了:standard 标准分词器以及 ik_smart 粗粒度 IK 分词器。
- Multi-match 检索
- Multi-match query 应用场景:多字段的 match query。
注意:多字段就涉及评分的整合,所以会有:most_fields、best_fields、cross_fields 等评分方式。
- Match_phrase_prefix 检索
- Match_phrase_prefix query 应用场景:短语匹配+前缀匹配的组合体,适用于短语前缀匹配。
- query_string 检索
- query_string query 应用场景:与或非表达式的检索。
AND:代表与,OR 代表或,NOT 代表非。
非常复杂的语法,建议参考官方文档。
- simple_query_string 检索
simple_query_string 应用场景:同 query_string 。
核心不同点:simple_query_string 在语法不对时,并不会报错。
组合检索类型
组合检索主要分为两大类:bool 组合检索和自定义评分检索。
- bool 组合检索
适用场景:复杂条件的组合检索。当单个或者单类检索条件不能适配复杂组合检索的时候,优先考虑 bool 组合条件检索。
其下可以包含但不限于:
must:必须满足条件。
must_not:必须不满足条件(忽略评分,召回数据评分为0)。
filter:过滤条件(忽略评分,召回数据评分为0),可以借助缓存提升性能。
should:部分条件满足,由minmum_should_match控制。
- 自定义评分检索
适用场景:传统基于BM25(词频TF、逆文档频率IDF)机制不能满足评分要求,某一个或者多个字段需要提升、降低或者修改权重比例的时候,优先考虑自定义评分实现。
如果自定义评分也无法满足,那只能自己开发评分插件实现。
自定义评分推荐阅读:实战 | Elasticsearch自定义评分的N种方法
总结
全文检索(Full text query)类检索
- Match 适用于:召回率高、精准度不高的场景;
- Match phrase 适用于:精准度高、召回率不高的场景;
- Match phrase prefix 适用于:短语前缀匹配检索;
- Mulit-match 适用于:多字段检索;
- Query string 适用于:支持与或非表达式的检索;
- Simple query string:较 query string 容错率高的场景;
精准匹配(Term-level query)类检索
- Term 适用于:单字段精准匹配;
- Terms 适用于:多字段精准匹配;
- Range 适用于:范围检索;
- Exists 适用于:判定是否存在检索;
- Wildcard 适用于:类Mysql like 检索,非必要不使用;
- prefix 适用于:前缀匹配检索;
- Fuzzy 适用于:支持编辑距离的模糊查询;
- IDs 适用于:基于文档id组检索的场景;
- Regexp 适用于:正则匹配检索,非必要不使用。