共计 4274 个字符,预计需要花费 11 分钟才能阅读完成。
本文首发于公众号:Hunter 后端
原文链接:es 笔记三之 term,match,match_phrase 等查询方法介绍
首先介绍一下在 es 里有两种存储字符串的字段类型,一个是 keyword,一个是 text。
keyword 在存储数据的时候是作为一个整体存储的,不会对其进行分词解决
text 存储数据的时候会对字符串进行分词解决,而后存储。
而对于查询方法,term 是准确查问,match 是含糊查问。
接下来咱们用几个例子,来别离表白下这两种类型的字段,应用 term,match,match_phrase 等搜寻的状况。
- 测试搜寻 keyword
- 测试搜寻 text
- match 的其余用法
- 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
,那么分词后的后果是 python
和 x
,然而 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 搜寻会先将其分词,变成 read
和 a
,而后匹配分词后蕴含这两个字符串一个或者两个的数据,在这里也会返回两条,一条的后果是 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 a
,a book
,read 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 是一个数组,外面是须要搜寻的字段。
如果想获取更多后端相干文章,可扫码关注浏览: