关于后端:es笔记三之termmatchmatchphrase-等查询方法介绍

45次阅读

共计 4274 个字符,预计需要花费 11 分钟才能阅读完成。

本文首发于公众号: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 是一个数组,外面是须要搜寻的字段。

如果想获取更多后端相干文章,可扫码关注浏览:

正文完
 0