前言

ES的无论什么搜索,对于text类型字段其实都是基于倒排索引去进行搜索的,也就是进行分词后的,因此如果想像传统数据库一样的模糊匹配,一般可以使用它的keyword进行搜索。(keyword不会被分词)
以下的搜索在大型生产环境都不推荐使用。

前缀索引查询

以xx开头的搜索,不计算相关度评分,和filter比,没有bitcache。前缀搜索,尽量把前缀长度设置的更长,性能差,一般大规模产品不使用。(是去倒排索引中去匹配前缀,需要遍历每一个倒排索引才能找到所有匹配的)

语法

GET index/_search
{"query": {"prefix": {"title": {"value": "text"}}}
}

为了加快前缀搜索速度,可以设置默认的 前缀索引 (空间换时间)

PUT my_index
{"mappings": {"properties": {"text": {"type": "text","index_prefixes": {"min_chars":2,  "max_chars":4}    }}}
}

上面这个设置的意思是,把分词后的每个词项的2-4个字符额外进行建立前缀倒排索引,从而提高后续前缀匹配的速度,但是占用空间也是相对变大。
index_prefixes: 默认 “min_chars” : 2, “max_chars” : 5 。

通配符查询

通配符查询类似于正则,但没正则强大,允许对匹配表达式进行通配符占位。

  • 表示匹配任意长度的任意字符
    ? 表示匹配一个任意字符
    […]则表示匹配括号中列出的字符中的任意一个
    [!..]表示不匹配括号中列出的字符中的任意一个

语法

{"query": {"wildcard": {"text": {"value": "eng?ish"}}}
}

正则查询

regexp查询的性能可以根据提供的正则表达式而有所不同。为了提高性能,应避免使用通配符模式,如.或 .?+未经前缀或后缀

语法

{"query": {"regexp": {"name": {"value": "[\\s\\S]*nfc[\\s\\S]*","flags": "ALL","max_determinized_states": 10000, #防止正则内存过大的保护措施"rewrite": "constant_score"}}}
}

关于参数flags,有几个配置可选:

ALL (Default)

启用所有可选操作符。

COMPLEMENT

启用操作符。可以使用对下面最短的模式进行否定。例如
a~bc # matches ‘adc’ and ‘aec’ but not ‘abc’
INTERVAL
启用<>操作符。可以使用<>匹配数值范围。例如
foo<1-100> # matches ‘foo1’, ‘foo2’ … ‘foo99’, ‘foo100’
foo<01-100> # matches ‘foo01’, ‘foo02’ … ‘foo99’, ‘foo100’

INTERSECTION

启用&操作符,它充当AND操作符。如果左边和右边的模式都匹配,则匹配成功。例如:
aaa.+&.+bbb # matches ‘aaabbb’

ANYSTRING

启用@操作符。您可以使用@来匹配任何整个字符串。
您可以将@操作符与&和~操作符组合起来,创建一个“everything except”逻辑。例如:
@&~(abc.+) # matches everything except terms beginning with ‘abc’

Fuzzy模糊(容错)匹配

场景

1、混淆字符 (box → fox)
2、缺少字符 (black → lack)
3、多出字符 (sic → sick)
4、颠倒次序 (act → cat)

在出现上面情况的时候,我们也希望用户可以搜索到想要的内容,那么这个时候可以使用fuzzy。

语法

以下两种都可以:

1、第一种-手动档
可以手动多指定一些参数,但一般也不建议改动

{"query": {"fuzzy": {"desc": {"value": "quangemneng","fuzziness": 5}}}
}

① value:(必需,字符串)
② fuzziness:(可选,字符串)最大误差 并非越大越好, 因为大了虽然召回率高 但是结果不准确
1) 两段文本之间的Damerau-Levenshtein距离是使一个字符串与另一个字符串匹配所需的插入、删除、替换和调换的数量
2) 距离公式:Levenshtein是lucene的,es改进版:Damerau-Levenshtein
3) axe=>aex Levenshtein=2 Damerau-Levenshtein=1

③ max_expansions:可选,整数)匹配的最大词项数量。默认为50。
④ prefix_length:创建扩展时保留不变的开始字符数。默认为0
1)避免在max_expansions参数中使用较高的值,尤其是当prefix_length参数值为时0。max_expansions由于检查的变量数量过多,参数中的高值 可能导致性能不佳。

⑤ transpositions:(可选,布尔值)指示编辑是否包括两个相邻字符的变位(ab→ba)。默认为true。
⑥ rewrite:(可选,字符串)用于重写查询的方法
https://www.elastic.co/cn/blog/found-fuzzy-search#performance-considerations

2、第二种,"自动挡"时代

{"query": {"match": {"desc": {"query": "quangengneng nfc","fuzziness": "AUTO"}}}
}

match_phrase_prefix(最简陋的Suggest)

match_phrase_prefix与match_phrase相同,但是它多了一个特性,就是它允许在文本的最后一个词项(term)上的前缀匹配,如果 是一个单词,比如a,它会匹配文档字段所有以a开头的文档,如果是一个短语,比如 “this is ma” ,他会先在倒排索引中做以ma做前缀搜索,然后在匹配到的doc中做match_phrase查询,(网上有的说是先match_phrase,然后再进行前缀搜索, 是不对的)

语法

{"query": {"match_phrase_prefix": {"desc": {"query": "zhichi quangongneng nf","analyzer": "whitespace","max_expansions": 1,"slop": 2,"boost": 1}}}
}

参数

analyzer

指定何种分析器来对该短语进行分词处理

max_expansions

限制匹配的最大term数。

  1. 一般来讲,前缀匹配是会全索引进行扫描匹配的,为了提高效率,可以进行限制它可以进行扫描的索引的个数,但即使设置为1,也不意味着返回的doc结果只有一个,主要有2点:
    1、一个索引可能有多个doc
    2、这个限制扫描个数是针对每个分片来说的(每个分片都可以扫描1个),因此也就是说该索引的每个分片扫描的第一个term都可能被匹配上。

boost

用于设置该查询的权重

slop

允许短语间的词项(term)间隔

slop 参数告诉 match_phrase 查询词条相隔多远时仍然能将文档视为匹配, 什么是相隔多远? 意思是说为了让查询和文档匹配你需要移动词条多少次?举个例子:

如果我们输入的是:de zhong shouji hongzhaji
而期望匹配的句子是:shouji zhong de hongzhaji
那么要怎么移动呢?
1、首先要把“shouji”词条向左移动2个词条:
shouji/de zhong shouji hongzhaji
2、接下来在把de向右移动2个词条:
shouji zhong de shouji hongzhaji

这样下来,共需要4次移动,因此slop需要设置为4的时候,输入的才能匹配上。

N-gram-tokenFilter

上面的前缀匹配还是存在性能问题,那有没有相对好一点的方法呢? 我们可以从分词角度出发。
在设置索引的时候,可以进行指定分词器的相关属性,其中有一项是指定fliter,可以通过指定ngram:

{"settings": {"analysis": {"filter": {"2_3_grams": {"type": "ngram","min_gram": 1,"max_gram": 2}},"analyzer": {"my_ngram": {"type":"custom","tokenizer": "standard","filter": [ "2_3_grams" ]}}}},"mappings": {"properties": {"text": {"type": "text","analyzer":"my_ngram","search_analyzer": "standard"}}}
}

经过ngram设置的min_gram:1和"max_gram": 3,分析以下语句:

GET _analyze
{"tokenizer": "ik_max_word","filter": [ "edge_ngram" ],"text": "reba always"
}

会先按最小粒度1进行拆分,也就是拆分出“r”,“e”,“b”,“a”,“a”,“l”,“w”,“a”,“y”,“s”
然后按粒度2拆分,拆分成:“re”,“eb”,“ba”,“al”,“lw”,“wa”,“ay”,“ys”
然后按最大粒度3进行拆分,拆分成:“reb”,“eba”,“alw”,“lwa”,“way”,“ays”

Edge-N-gram-tokenFilter

另外一个filter,根据min_gram和max_gram对分词的开头部分进行拆分。
这个可能更常用一些,因为更多的我们的搜索是从一个词的开头进行部分搜索,而不是中间进行搜索。

GET _analyze
{"tokenizer": "ik_max_word","filter": [ "edge_ngram" ],"text": "reba always loves me"
}

min_gram =1 “max_gram”: 1
拆分情况:r a l m

min_gram =1 “max_gram”: 2
拆分情况:
r a l m
re al lo me

min_gram =2 “max_gram”: 3
拆分情况:
re al lo me
reb alw lov me

ES第十三天-扩展查询-前缀匹配、通配符查询、正则查询、模糊匹配、句子前缀匹配相关推荐

  1. ES 查询一,基于URL 的查询

    开始查询 GET {index} # 1. 查看,索引结构 GET {index}/_search # 2. 查看,索引的所有数据.(ES 查询使用 _search 关键字) GET {index}/ ...

  2. es查询语句拼接 java_JAVA使用ElasticSearch查询in和not in的实现方式

    JAVA使用ElasticSearch查询in和not in的实现方式 发布时间:2020-08-22 16:03:11 来源:脚本之家 阅读:119 作者:执笔记忆的空白 ElasticSearch ...

  3. ElasticSearch 6.3版本(ES)查询人名关键字不拆词查询

    ElasticSearch 6.3版本(ES)查询关键字不拆词查询:类似mysql 的 like 语句. mysql的sql语法类似如下,采用大量like和locate语法,进行模糊查询,导致查询一个 ...

  4. [深入学习C#]LINQ查询表达式详解(1)——基本语法、使用扩展方法和Lambda表达式简化LINQ查询

    此文章非原创,转载自诗人江湖老,原文地址 在Git上下载源码 在工程中我们少不了要定义类或者结构去储存数据,这些数据将被临时地储存在内存中,现在我们想要对其完成一些类似于查找.过滤等等常见的任务的时候 ...

  5. 为什么mysql查询结果有前缀_字符串的公共前缀对Mysql B+树查询影响回溯分析

    年前项目组接微信公众号. 上线之后,跟微信相关的用cid列的查询会话的SQL变慢了几十倍!思考这个问题思考了非常久.从出现以来一直是我心头的一个结.cid这一列是建了索引的,普通的cid列更新都没问题 ...

  6. ES中如何实现类似having的先聚合再过滤查询

    一.问题描述: 在mysql数据库中,我们可以很方面的通过having关键字实现对聚合结果的过滤查询.那么,在ES中该如何实现类似having的先聚合再过滤查询呢? 二.业务场景: 需要找出下单次数大 ...

  7. ElasticSearch高级 (Query DSL查询 bulk批量操作 导入数据 各种查询 实战技巧-优化比重 全量与增量数据同步)

    ElasticSearch高级 01-Query DSL(Domain Specific Language) 1 查询上下文 2 相关度评分:_score 3 元数据:_source 4 Query ...

  8. 用PostgreSQL 做实时高效 搜索引擎 - 全文检索、模糊查询、正则查询、相似查询、ADHOC查询...

    用PostgreSQL 做实时高效 搜索引擎 - 全文检索.模糊查询.正则查询.相似查询.ADHOC查询 作者 digoal 日期 2017-12-05 标签 PostgreSQL , 搜索引擎 , ...

  9. PostgreSQL 实时高效搜索 - 全文检索、模糊查询、正则查询、相似查询、ADHOC查询...

    标签 PostgreSQL , 搜索引擎 , GIN , ranking , high light , 全文检索 , 模糊查询 , 正则查询 , 相似查询 , ADHOC查询 背景 字符串搜索是非常常 ...

最新文章

  1. 《用Python进行自然语言处理》第6章 学习分类文本
  2. OpenCASCADE绘制测试线束:OCAF 命令之应用命令
  3. OpenID 和 OAuth 的区别及第三方登录的安全隐患分析
  4. JavaScript强化教程 —— JavaScript 总结
  5. java 写文件缓存,java泛型实现文件缓存
  6. 2.8 GloVe 词向量
  7. 轻松实现SQL异地备份
  8. 测试文档模板_学会word2007创建自定义模板的方法,让你新建的文档结构都一致...
  9. 【MAVEN】搜索错误“Index downloads are disabled,search results may be incomplete”
  10. Python(二)JavaPython混合编程
  11. 简单的Map集合练习题
  12. 常见的软件测试方法有,常见的几种软件测试方法都有哪些
  13. nodejs mysql process_nodeJS之进程process对象
  14. mysql错误1273_mysql8 参考手册--错误代码1273-1294
  15. bibtex引用参考文献排版格式
  16. App Inventor学习环境搭建
  17. 来了老弟,帅气模态框
  18. linux7 etc下的grub2,Centos7安装 grub2 配置技巧:改变启动顺序
  19. 为什么说OKRS-E是适合的OKR框架
  20. 《中国高血压防治指南2010》学习笔记-完成

热门文章

  1. 二道题:分组顺序向下填充 和 标注数据整理
  2. 【小白从小学Python、C、Java】【计算机等级考试二级-必会题】【ASCII码与字符相互转化】
  3. 快速入门Mybatis初学笔记(二)
  4. java 执行长事物_狂 热 和 许 诺
  5. 【PowerDesigner】Powerbuilder 11.5破解方法
  6. PowerDesigner 安装
  7. java时间规范化_Java日期时间使用总结
  8. 教育小孩用一个白脸一个红脸不合适
  9. “信号声源定位实验”
  10. 黑客每小时发送3万封性勒索邮件:轻松月入11万!