本文首发于公众号:Hunter后端

原文链接:es笔记三之term,match,match_phrase 等查询方法介绍

首先介绍一下在 es 里有两种存储字符串的字段类型,一个是 keyword,一个是 text。

keyword 在存储数据的时候是作为一个整体存储的,不会对其进行分词处理

text 存储数据的时候会对字符串进行分词处理,然后存储。

而对于查询方法, term 是精确查询,match 是模糊查询。

接下来我们用几个例子,来分别表达下这两种类型的字段,使用 term,match,match_phrase 等搜索的情况。

  1. 测试搜索 keyword
  2. 测试搜索 text
  3. match 的其他用法
  4. multi-match 搜索

首先我们创建这样一个 index 和下面几条数据:

PUT /exam

PUT /exam/_mapping
{
"properties": {
"address": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "keyword"
}
}
}

我们创建了 name 字段为 keyword,address 字段是 text,接下来我们先创建几条数据来测试 keyword 字段类型的搜索。

1、测试搜索 keyword

写入数据:

PUT /exam/_doc/1
{
"name" : "hunter x",
"address": "i study english"
} PUT /exam/_doc/2
{
"name" : "python x",
"address": "this is python x"
} PUT /exam/_doc/3
{
"name" : "hunter python",
"address": "i live in china"
} PUT /exam/_doc/4
{
"name" : "hunter java",
"address": "read a book"
} PUT /exam/_doc/5
{
"name" : "java golang python",
"address": "you can get a good job"
} PUT /exam/_doc/6
{
"name" : "js python",
"address": "wanna go out to play"
}

name 字段类型为 keyword,所以它存储的时候是以整体来存储的。

接下来介绍这几种查询方式查询 name 字段的操作。

term

精确查找,对于搜索的内容也是直接整体查找,也就是说搜索什么内容就查询什么内容。

比如对于我们写入的 id=2 的数据,要想查 name='python x' 的数据,就需要查询的字符串和结果完全匹配才可返回,比如下面的操作操作:

GET /exam/_search
{
"query": {
"term": {
"name": {
"value": "python x"
}
}
}
}

match

match 的操作是将搜索的内容进行分词后再查询,比如我们 match 的参数是 python x,那么分词后的结果是 pythonx,但是 keyword 类型的字段数据不会分词,所以也需要能够完全匹配才能查询得到,所以这里就会去查找 name 字段里只包含了 python 和 x 的数据。

GET /exam/_search
{
"query": {
"match": {
"name": "python x"
}
}
}

2、测试搜索 text

前面的 keyword 类型的字段搜索需要把握的是完全一样就行,而对于 text 字段的搜索,text 字段的内容在写入 es 时本身会被分词处理,所以搜索 text 的处理并不完全一样。

在这里,我么用的 address 字段是 text 类型,我们还是用前面的示例作为演示。

term

term 的搜索是不分词的,搜索给定字符串的全部内容,比如对于我们插入的 id=4 的那条数据,address 的内容是 read a book,它被分词为三个,read、a、book,所以我们使用 term 方法搜索下面三个都可以搜到这条数据:

GET /exam/_search
{"query": {"term": {"address": "read"}}} GET /exam/_search
{"term": {"address": "a"}} GET /exam/_search
{"term": {"address": "book"}}

但是,如果我们 address 后面的值如下这种就搜索不到了,因为 term 操作并不会给搜索的内容进行分词,而是作为一个整体进行搜索:

GET /exam/_search
{"query": {"term": {"address": "read a"}}} GET /exam/_search
{"query": {"term": {"address": "a book"}}} GET /exam/_search
{"query": {"term": {"address": "read a book"}}}

但是还有一种情况,那就是对于搜索的 text 字段后加上 .keyword 字段的操作,这个相当于将 address 不分词进行搜索,将 address 这个字段看作是一个 keyword 来操作,可以理解成是使用 term 来搜索 keyword 字段,就是上一个类型的操作。

所以下面的这个操作就是可以搜索到 address='read a book' 的数据

GET /exam/_search
{"query": {"term": {"address.keyword": "read a book"}}}

match

match,模糊匹配,在匹配前会将搜索的字符串进行分词,然后将匹配上的数据按照匹配度(在 es 里有一个 _score 字段用于表示这种匹配程度)倒序返回。

比如我们对 address 字段搜索字符串 a,会返回两条数据,id 为 4 和 5 的,因为 address 字段进行分词存储后都包含这个字符串。

GET /exam/_search
{"query": {"match": {"address": "a"}}}

或者我们搜索内容为 read a,match 搜索会先将其分词,变成 reada,然后匹配分词后包含这两个字符串一个或者两个的数据,在这里也会返回两条,一条的结果是 read a book,一条是 you can get a good job,因为这两条数据都包含字符串 a,但是因为前者分别满足了两个搜索的条件,所以前者的匹配度会更高,所以作为第一条数据返回:

GET /exam/_search
{"query": {"match": {"address": "read a"}}}

match_phrase

匹配短语,使用这个方法不加其他参数的情况下,可以看作是会匹配包含这个短语、且顺序一致的数据。

比如说对于 address="read a book" 的数据,搜索 read aa bookread a book 都可以筛选到这条数据。

GET /exam/_search
{"query": {"match_phrase": {"address": "read a"}}} GET /exam/_search
{"query": {"match_phrase": {"address": "a book"}}} GET /exam/_search
{"query": {"match_phrase": {"address": "read a book"}}}

但是如果搜索 book a,因为顺序不一致,所以下面的搜索是无法搜素到该数据的:

GET /exam/_search
{"query": {"match_phrase": {"address": "book a"}}}

但是 match_phrase 有一个 slop 参数可以用于忽略这种顺序,也就是允许搜索的关键词错位的个数,比如 'book a',分词后的 'book' 和 'a' 如果允许错位两个顺序(a 往前挪一个,book 往后挪一个,这是我理解的 slop 的操作用法),那么就可以筛选到我们这条数据,示例如下:

GET /exam/_search
{
"query": {
"match_phrase": {
"address": {
"query": "book a",
"slop": 2
}
}
}
}

match_phrase_prefix

匹配前缀,比如对于 address 值为 'read a book' 的数据,我们只知道的值是 'read a bo',想要根据这个搜索词搜索完整的数据,就可以用到 match_phrase_prefix。

他的用法是这样的,先将检索词分词,然后将最后一个分词结果单独去匹配,所以这个搜索词的过程就是先根据 'read a' 的分词结果搜索到一些数据,然后根据剩下的 'bo' 去匹配满足这个前缀的数据:

GET /exam/_search
{"query": {"match_phrase_prefix": {"address": "read a bo"}}}

3、match 的其他用法

匹配分词后的全部结果

对于 match,前面我们介绍过会先将搜索的字符串分词,然后去筛选包含分词结果一至多个的结果。

比如前面介绍的搜索 'read a',会搜索出 'read a book' 以及 'you can get a good job',因为他们都包含分词的结果 'a',这种操作就类似于用 should 去对分词结果进行进一步的搜索操作,

但是如果我们想要更精确,搜索的内容必须包含分词的全部结果 'read' 和 'a',我么可以加上 operator 参数:

GET /exam/_search
{
"query": {
"match": {
"address": {
"query": "read a",
"operator": "and"
}
}
}
}

这样操作结果就是筛选了包含全部搜索词分词后结果的数据。

匹配的模糊处理

我们可以通过 fuzziness 字段来打开字符模糊匹配的开关,最简单的一个例子就是比如我们搜索 'read',打字不小心打成了 'raed',这种就可以实现他的模糊匹配:

GET /exam/_search
{
"query": {
"match": {
"address": {
"query": "raed a",
"operator": "and",
"fuzziness": 1
}
}
}
}

4、multi-match 搜索

前面我们的 match 参数操作的都是针对于单个字段,multi_match 则可以针对于多个字段进行 match 操作,这个需要都能匹配上搜索的关键字,使用示例如下:

GET /exam/_search
{
"query": {
"multi_match": {
"query": "python",
"fields": ["name", "address"]
}
}
}

其中,fields 是一个数组,里面是需要搜索的字段。

如果想获取更多后端相关文章,可扫码关注阅读:

es笔记三之term,match,match_phrase 等查询方法介绍的更多相关文章

  1. 白日梦的ES笔记三:万字长文 Elasticsearch基础概念统一扫盲

    目录 一.导读 二.彩蛋福利:账号借用 三.ES的Index.Shard及扩容机制 四.ES支持的核心数据类型 4.1.数字类型 4.2.日期类型 4.3.boolean类型 4.4.二进制类型 4. ...

  2. iOS 学习笔记三【segmentedControl分段控制器详细使用方法】

    在iOS开发过程中,分段控制器的使用频率还是蛮高的,下面是我写的一个简单的demo,大家可以把代码直接复制过去,就可以使用,ios9最新支持. // // ViewController.m // 03 ...

  3. 多线程学习笔记(四)---- Thread类的其他方法介绍

    一.wait和 sleep的区别 wait可以指定时间也可以不指定时间,而sleep必须指定时间: 在同步中时,对cpu的执行权和锁的处理不同: wait:释放执行权,释放锁:释放锁是为了别人noti ...

  4. Java_jdbc 基础笔记之十一数据库连接 (通用的查询方法)

    鉴于之前的查询方法,在这里我们可以写一个通用的方法 /** * 鉴于 student.和customer查询的方法有好多相同之处,在此可以写一个通用的方法 */ public <T> T ...

  5. Django笔记三十三之缓存操作

    本文首发于公众号:Hunter后端 原文链接:Django笔记三十三之缓存操作 这一节介绍一下如何在 Django 中使用 redis 做缓存操作. 在 Django 中可以有很多种方式做缓存,比如数 ...

  6. ElasticSearch match, match_phrase, term区别

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

  7. elasticsearch term match multi_match区别

    转自:http://www.cnblogs.com/yjf512/p/4897294.html match 最简单的一个match例子: 查询和"我的宝马多少马力"这个查询语句匹配 ...

  8. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  9. VSTO学习笔记(三) 开发Office 2010 64位COM加载项

    原文:VSTO学习笔记(三) 开发Office 2010 64位COM加载项 一.加载项简介 Office提供了多种用于扩展Office应用程序功能的模式,常见的有: 1.Office 自动化程序(A ...

  10. angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令

    在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...

随机推荐

  1. 如何使用Github创建一个仓库

    创建仓库(对我来说,这是新建) 点击这里的Create repository: 进入到这样一个界面: 其中,Repository name,是我们即将创建完成的仓库名称: 而这里: 需要填写的是对仓库 ...

  2. 65.C++的输入流和输出流

    1.流的概念和流类库的结构   程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件.   C++输入输出包含以下三个方面的内容:   对系统指定的标准设备的输入和输 ...

  3. Nacos 实现 AP+CP原理[Raft 算法 NO]

    来源于网络 一.什么是 Raft算法 Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它.为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导 ...

  4. QGIS 导入文本数据(WKT)

    在做GIS数据处理的时候,经常会遇到原始数据是 text.csv.Excel 等格式的数据.要使用数据前提是要先转换数据. 这里是介绍用 QGIS 导入数据.打开导入方式如下(根据自己的文本类型选择不 ...

  5. 5.Web信息收集

    Web信息收集 目录 Web信息收集 1.whois查询 2.服务器操作系统的识别 3.服务器加固 4.服务版本识别 5.常见组合: 6.指纹识别 7.敏感路径识别 8.历史漏洞信息收集 1.whoi ...

  6. 你需要知道的Symbols

    著名symbol 著名symbol是一个在不同领域中都相同且未注册的symbol.如果我们要列出著名symbol,它们会是: Symbol.iterator Symbol.toStringTag Sy ...

  7. FileReader之获取文本文件内容为字符串

    FileReader之获取文本文件内容为字符串 FileReader官网描述: FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 Fil ...

  8. MySQL相关知识点思维导图整理

    MySQL相关知识点思维导图整理 Xmind思维导图下载地址: 蓝奏云:https://shuihan.lanzoui.com/iXZw7frkn5a

  9. Oracle_表空间

    Oracle 表空间 在执行具体的操作之前,由于Oracle不允许删除现有临时表空间,所以在删除现有临时表空间时要终止现有的实时会话. 查询Oracle表空间名称,表空间物理文件路径 查询临时表空间: ...

  10. AF_XDP技术简介

    本文分享自天翼云开发者社区@<AF_XDP技术简介>,作者: l****n 一.概述 AF_XDP 是一项新增的,针对高性能数据包处理进行优化的地址族协议.本文档假设读者已经熟悉 BPF ...