本文首发于公众号: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 和下面几条数据:

  1. PUT /exam
  2. PUT /exam/_mapping
  3. {
  4. "properties": {
  5. "address": {
  6. "type": "text",
  7. "fields": {
  8. "keyword": {
  9. "type": "keyword",
  10. "ignore_above": 256
  11. }
  12. }
  13. },
  14. "name": {
  15. "type": "keyword"
  16. }
  17. }
  18. }

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

1、测试搜索 keyword

写入数据:

  1. PUT /exam/_doc/1
  2. {
  3. "name" : "hunter x",
  4. "address": "i study english"
  5. }
  6. PUT /exam/_doc/2
  7. {
  8. "name" : "python x",
  9. "address": "this is python x"
  10. }
  11. PUT /exam/_doc/3
  12. {
  13. "name" : "hunter python",
  14. "address": "i live in china"
  15. }
  16. PUT /exam/_doc/4
  17. {
  18. "name" : "hunter java",
  19. "address": "read a book"
  20. }
  21. PUT /exam/_doc/5
  22. {
  23. "name" : "java golang python",
  24. "address": "you can get a good job"
  25. }
  26. PUT /exam/_doc/6
  27. {
  28. "name" : "js python",
  29. "address": "wanna go out to play"
  30. }

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

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

term

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

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

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "term": {
  5. "name": {
  6. "value": "python x"
  7. }
  8. }
  9. }
  10. }

match

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

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name": "python x"
  6. }
  7. }
  8. }

2、测试搜索 text

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

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

term

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

  1. GET /exam/_search
  2. {"query": {"term": {"address": "read"}}}
  3. GET /exam/_search
  4. {"term": {"address": "a"}}
  5. GET /exam/_search
  6. {"term": {"address": "book"}}

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

  1. GET /exam/_search
  2. {"query": {"term": {"address": "read a"}}}
  3. GET /exam/_search
  4. {"query": {"term": {"address": "a book"}}}
  5. GET /exam/_search
  6. {"query": {"term": {"address": "read a book"}}}

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

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

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

match

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

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

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

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

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

match_phrase

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

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

  1. GET /exam/_search
  2. {"query": {"match_phrase": {"address": "read a"}}}
  3. GET /exam/_search
  4. {"query": {"match_phrase": {"address": "a book"}}}
  5. GET /exam/_search
  6. {"query": {"match_phrase": {"address": "read a book"}}}

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

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

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

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "match_phrase": {
  5. "address": {
  6. "query": "book a",
  7. "slop": 2
  8. }
  9. }
  10. }
  11. }

match_phrase_prefix

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

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

  1. GET /exam/_search
  2. {"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 参数:

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "match": {
  5. "address": {
  6. "query": "read a",
  7. "operator": "and"
  8. }
  9. }
  10. }
  11. }

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

匹配的模糊处理

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

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "match": {
  5. "address": {
  6. "query": "raed a",
  7. "operator": "and",
  8. "fuzziness": 1
  9. }
  10. }
  11. }
  12. }

4、multi-match 搜索

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

  1. GET /exam/_search
  2. {
  3. "query": {
  4. "multi_match": {
  5. "query": "python",
  6. "fields": ["name", "address"]
  7. }
  8. }
  9. }

其中,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. Java笔记第十二弹

    Lambda表达式的标准格式 三要素:形式参数.箭头.代码块 格式:(形式参数)->(代码块) 形式参数:如果有多个参数,参数之间用逗号隔开:如果没有参数,留空即可 ->代表指向动作 La ...

  2. Android笔记--对话框

    提醒对话框AlertDialog 具体实现: 相关用法: 日期对话框DatePickerDialog DatePicker 具体实现: 使用Dialog选择日期: 时间对话框TimePickerDia ...

  3. LeetcodePractice-数组

    目录 88. 合并两个有序数组 思路解析 字节&1. 两数之和 思路解析 腾讯&15. 三数之和 思路解析 18. 四数之和 思路解析 解释下,tmpSum为什么用int不行,需要用i ...

  4. Cesium 后处理(Post Process)

    原文地址:https://blog.csdn.net/ls870061011/article/details/123910821 作者:GIS李胜 为实现三维模型的更炫.更酷.更美观,Cesium在1 ...

  5. vulnhub靶场之WIRELESS: 1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:Wireless: 1,下载地址:https://download.vulnhub.com/wireless/Mystiko-Wireless. ...

  6. 手动实现一个call bind

    一.call的实现(apply类似) //完成版 Function.prototype.setCall = function (obj){ var object = obj || window let ...

  7. 位运算符n&(n-1)详解与妙用

    用处一:求一个int类型数是否为2的幂 1.当n=4时,二进制为:0100 n-1=3,二进制为:0011 则:n&(n-1)==0  解释(将0100最右边的1变为0 则 0000=0) 2 ...

  8. 浅谈Vue 2.x当中组件之间传值方式

    一.父子之间传值 1. 父传子 :props <!DOCTYPE html> <html lang="en"> <head> <meta ...

  9. 《HelloTester》第4期

    1.前言 终于到了谈面试的部分了! 我在这也说明一下,有同学说之前简历篇的时候一直在说项目的介绍,而面试官真正关心的是技术啊?我在这做个解释,因为我写的这些文章主要针对的是软件测试的同学,所以其他职位 ...

  10. 【Spring专题】「技术原理」从源码角度去深入分析关于Spring的异常处理ExceptionHandler的实现原理

    ExceptionHandler的作用 ExceptionHandler是Spring框架提供的一个注解,用于处理应用程序中的异常.当应用程序中发生异常时,ExceptionHandler将优先地拦截 ...