要搞懂 Elasticsearch Match Query,看这篇就够了

本文通过实例讲解Elasticsearch中MatchQuery的使用场景及参数意义,包括operator、analyzer、lenient、fuzziness、zeroterms_query、cutoff_frequency、synonyms等属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 前言

Match Query 是最常用的 Full Text Query 。无论需要查询什么字段, match 查询都应该会是首选的查询方式。它既能处理全文字段,又能处理精确字段。

2. 构建示例

为了能够在后面能深入理解 Match Query 中的各个属性的意义,我们先构建一个 index 示例(有兴趣的同学只要将下面字段粘贴到 sense 中就可以创建)。

PUT matchtest
{ 
}

PUT matchtest/_mapping/people
{
  "properties": {
    "age": {
      "type": "integer"
    },
    "hobbies": {
      "type": "text"
    },
    "name": {
      "type": "keyword"
    }
  }
}

PUT matchtest/people/1
{
  "name" : "Jim",
  "age": 10,
  "hobbies": "football, basketball, pingpang"
}


PUT matchtest/people/2
{
  "name" : "Tom",
  "age": 12,
  "hobbies": "swimming, football"
}

3. match

3.1 operator 参数

match 查询是一种 bool 类型的查询。什么意思呢?举个例子,查询 people type 的 hobbies 为 football和basketball。

GET matchtest/people/_search
{
  "query": {
    "match": {
      "hobbies": "football basketball"
    }
  }
}

会将上面的两个文档都搜索出来。为什么?上面的查询其实隐藏了一个默认参数operator , 它的默认值是 or ,也就是说上面的查询也可以写成这种形式:

GET matchtest/people/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "football basketball",
        "operator": "or"
      }
    }
  }
}

这样就比较容易理解了,既然是 or 操作符,就表示只要查询的文档的 hobbies 字段中含有 football 和 basketball 任意一个,就可以被匹配到。

如果将 operator 操作符的值改为 and ,则表示需要同时包含 football 和 basketball , 得到的结果就只能是 文档 1 Jim 小朋友了。

3.2 analyzer

analyzer 属性是指在对查询文本分析时的分析器

  • 如果没有指定则会使用字段mapping 时指定的分析器
  • 如果字段在 mapping 时也没有明显指定,则会使用默认的 search analyzer。

这里我们也没有指定,就会使用默认的,就不举例了,在后面文章讲解 analyzer 时再拓展。

3.3 lenient 参数

lenient:宽容

默认值是 false , 表示用来在查询时如果数据类型不匹配且无法转换时会报错。如果设置成 true 会忽略错误。

例如, 例子中的 age 是 integer 类型的,如果查询 age=xxy ,就会导致无法转换而报错。

GET matchtest/_search
{
  "query": {
    "match": {
      "age" : {
        "query": "xxx"
      }
    }
  }
}

而如果将 lenient 参数设置为 true ,就会忽略这个错误。

GET matchtest/_search
{
  "query": {
    "match": {
      "age" : {
        "query": "xxx",
        "lenient": true
      }
    }
  }
}

注意:
如果将 age 字段的值设置为字符串 “10”, 来查询,由于能够转换成整数,这时 elastic 内部会将 字符串先转换成整数再做查询,不会报错。

4. Fuzziness

4.1 fuzzniess 参数

fuzziness 参数可以是查询的字段具有模糊搜索的特性。来先了解下什么是模糊搜索。

4.1.1 什么是模糊搜索?

模糊搜索是指系统允许被搜索信息和搜索提问之间存在一定的差异,这种差异就是“模糊”在搜索中的含义。例如,查找名字Smith时,就会找出与之相似的Smithe, Smythe, Smyth, Smitt等。
——百度百科

通过模糊搜索可以查询出存在一定相似度的单词,那么怎么计算两个单词是否有相似度以及相似度的大小呢?这就要了解下另外一个概念:Levenshtein Edit Distance

4.1.2 Levenshtein Edit Distance

Levenshtein Edit Distance 叫做莱文斯坦距离,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。允许的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如,单词 “god” 只需要插入一个 ‘o’ 字符就可以变为 “good”,因此它们之间的编辑距离为 1。

4.1.3 fuzziness 参数取值规则

了解了上面两个概念,回过头再来看下 fuzziness 参数。

在查询 text 或者 keyword 类型的字段时, fuzziness 可以看做是莱文斯坦距离。

fuzziness 参数的取值如下:

  • 0,1,2 :表示最大可允许的莱文斯坦距离
  • AUTO
    会根据词项的长度来产生可编辑距离,它还有两个可选参数,形式为AUTO:[low],[high], 分别表示短距离参数和长距离参数;如果没有指定,默认值是 AUTO:3,6 表示的意义如下:
    0..2:单词长度为 0 到 2 之间时必须要精确匹配,这其实很好理解,单词长度太短是没有相似度可言的,例如 ‘a’ 和 ‘b’。
    3..5:单词长度 3 到 5 个字母时,最大编辑距离为 1
    >5:单词长度大于 5 个字母时,最大编辑距离为 2

最佳实践: fuzziness 在绝大多数场合都应该设置成 AUTO

如果不设置 fuziness 参数,查询是精确匹配的。

来看例子,下面创建了一个 doc:

PUT matchtest/people/1
{
  "name" : "Jim",
  "age": 10,
  "hobbies": "football, basketball, pingpang"
}

设置 fuzziness 为 AUTO

其中 hobbies 字段的值 football 长度 > 5, 此时我们找一个编辑距离为 2 的单词 footba22 来查询,应该匹配到,
其中 name 字段的值 jim 长度在 3 和 5 之间,此时找一个编辑距离为 1 的单词 jiO 应匹配到,而编辑距离为 2 的 jOO 就不应匹配到。

GET matchtest/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "footba22",
        "fuzziness": "AUTO"
      }
    }
  }
}

GET matchtest/_search
{
  "query": {
    "match": {
      "name": {
        "query": "jiO",
        "fuzziness": "AUTO"
      }
    }
  }
}


GET matchtest/_search
{
  "query": {
    "match": {
      "name": {
        "query": "jOO",
        "fuzziness": "AUTO"
      }
    }
  }
}
4.2 prefix_length

prefix_length 表示不能被模糊化的初始字符数。由于大部分的拼写错误发生在词的结尾,而不是词的开始,使用 prefix_length 就可以完成优化。

注意:
prefix_length 必须结合 fuzziness 参数使用。

例如,在查询 hobbies 中的 football 时,将 prefix_length 参数设置为 3,这时 foatball 将不能被匹配。

GET matchtest/_search
{
  "query": {
    "match": {
      "hobbies": {
        "query": "foatball",
        "fuzziness": "AUTO",
        "prefix_length": 3
      }
    }
  }
}

5. Zero terms Query

先看例子, 先创建一个文档 zero_terms_query_test 其中 message 字段使用 stop 分析器,这个分析器会将 stop words 停用词在索引时全都去掉。

PUT matchtest1

PUT matchtest1/_mapping/zero_terms_query_test
{
  "properties": {
    "message": {
      "type": "text",
      "analyzer": "stop"
    }
  }
}


PUT matchtest1/zero_terms_query_test/1
{
  "message": "to be or not to be"
}

GET matchtest1/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be or not to be",
        "operator": "and",
        "zero_terms_query": "none"
      }
    }
  }
}

那么就像 message 字段中的 to be or not to be 这个短语中全部都是停止词,一过滤,就什么也没有了,得不到任何 tokens, 那搜索时岂不什么都搜不到。

POST _analyze
{
  "analyzer": "stop",
  "text": "to be or not to be"
}

zero_terms_query 就是为了解决这个问题而生的。它的默认值是 none ,就是搜不到停止词(对 stop 分析器字段而言),如果设置成 all ,它的效果就和 match_all 类似,就可以搜到了。

GET matchtest1/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be or not to be",
        "operator": "and",
        "zero_terms_query": "all"
      }
    }
  }
}

6. Cutoff frequency

查询字符串时的词项会分成低频词(更重要)和高频词(次重要)两类,像前面所说的停用词 (stop word)就属于高频词,它虽然出现频率较高,但在匹配时可能并不太相关。

实际上,我们往往是想要文档能尽可能的匹配那些低频词,也就是更重要的词项。

要实现这个需求,只要在查询时配置 cutoff_frequency 参数就可以了。假设我们将 cutoff_frequency 设置成 0.01 就表示:

  • 任何词项在文档中超过 1%, 被认为是高频词
  • 其他的词项会被认为低频词

从而将高频词(次重要的词)挪到可选子查询中,让它们只参与评分,而不参与匹配;高频词(更重要的词)参与匹配和评分。

这样一来,就不再需要 stopwords 停用词文件了,从而变成了动态生成停用词: 高频词就会被看做是停用词。这种配置只是对于词项比较多的场合如 email body,文章等适用,文字太少, cutoff_frequency 选项设置的意义就不大了。

cutoff_frequency 配置有两种形式:

  • 指定为一个分数( 0.01 )表示出现频率
  • 指定为一个正整数( 5 )则表示出现次数

下面给个例子, 在创建的 3 个文档中都包含 "be " 的单词,在查询时将 cutoff_frequency 参数设置为 2, 表示 “be” 就是高频词,只会参与评分,但在匹配时不做考虑。

此时查询的内容为 “to be key” ,由于 “be” 词项是高频词,因为在文档中必须要存在 “to” 或者 “key” 才能匹配,因此文档 3 不能匹配。

PUT /matchtest2

PUT matchtest2/_mapping/cutoff_frequency_test
{
  "properties": {
    "message": {
      "type": "text"
    }
  }
}

PUT matchtest2/cutoff_frequency_test/1
{
  "message": "to be or not to be to be or"
}

PUT matchtest2/cutoff_frequency_test/2
{
  "message": "be key or abc"
}

PUT matchtest2/cutoff_frequency_test/3
{
  "message": "or to be or to to be or"
}

GET matchtest2/_search
{
  "query": {
    "match": {
      "message": {
        "query": "to be key",
        "cutoff_frequency": 2
      }
    }
  }
}

7. synonyms

synonyms 是指同义词,只要索引和字段中配置了同义词过滤器,match 查询是支持多词条的同义词扩展的。在应用过滤器后,解析器会对每个多次条同义词创建一个语句查询。

例如,同义词 USA, united states of America 就会构建出 (USA OR (“united states of America”))。看下面例子:

PUT /matchtest4
{
    "settings": {
        "index" : {
            "analysis" : {
                "analyzer" : {
                    "synonym" : {
                        "tokenizer" : "whitespace",
                        "filter" : ["synonym"]
                    }
                },
                "filter" : {
                    "synonym" : {
                        "type" : "synonym",
                        "synonyms" : [
                            "USA, united states of America"
                        ]
                    }
                }
            }
        }
    }
}

PUT /matchtest4/_mapping/synonyms_test
{
  "properties": {
    "message": {
      "type": "text",
      "analyzer": "synonym"
    }
  }
}

PUT /matchtest4/synonyms_test/1
{
  "message": "united states of America people"
}


GET /matchtest4/_search
{
  "query": {
    "match": {
      "message": {
        "query": "USA"
      }
    }
  }
}

8. 总结

本文以代码实例的方式完整的讲解了 Match Query 的各种使用场景和参数意义。


转自:https://segmentfault.com/a/1190000017110948
<think>嗯,用户想了解Elasticsearch中的Match Query,我需要详细解释这个查询类型。首先,得确定用户对Elasticsearch的基础知识是否了解,但可能他们已经有基本概念,所以直接从Match Query开始。 首先,Match Query属于全文搜索的一种,和Term Query的区别可能需要说明。比如,Match会对输入文本进行分析,而Term不会。这里要提到分析器的处理,比如分词、转小写等步骤。 然后,结构部分,用户可能需要知道如何编写一个Match Query的DSL语句。给出一个基本的JSON示例,比如查询"message"字段包含"quick brown fox"的情况。这时候要注意,默认操作符是OR还是AND,用户可能会混淆,需要明确说明,并给出operator参数的用法。 接下来,参数部分很重要。常用的参数包括operator、fuzziness、prefix_length、analyzer等。每个参数的作用和适用场景要解释清楚。例如,fuzziness用于模糊匹配,处理拼写错误,而prefix_length控制模糊匹配时起始字符不变的数量。 高级特性方面,比如multi_match,可以扩展到多个字段查询,这里需要简单提及,但可能用户更关注单字段的Match Query。同义词和停用词处理也是分析器的一部分,但可能需要提醒用户这些功能依赖于分析器的配置。 性能优化方面,Match Query因为是全文搜索,涉及到分析过程,相比Term Query会更耗资源。使用短语匹配或者结合keyword字段进行精确匹配可能更高效,这些是实际使用中需要注意的地方。 最后,总结Match Query的适用场景,比如需要分词、模糊匹配、处理同义词的情况,以及何时选择其他查询类型。确保用户能根据需求选择合适的查询方式。 可能用户在实际使用中遇到的问题包括为什么某些文档没被检索到,是否因为分词问题或者操作符设置不正确。这时候需要检查分析器的效果和operator的参数设置。另外,模糊匹配的参数调整也是常见问题,需要指导如何根据实际情况调整fuzziness和prefix_length。 整体结构需要清晰,分点讲解,让用户能逐步理解Match Query的各个方面,同时提供示例帮助理解。避免使用过于专业的术语,或者至少解释清楚术语的含义,确保不同层次用户都能理解。</think>好的,我来为您详细讲解 Elasticsearch 中的 **Match Query**,这是最常用的全文搜索查询之一。内容会分以下几个部分: --- ### 一、Match Query 的核心特点 1. **全文搜索**:专为处理文本内容设计,会对查询文本进行**分词处理** 2. **分析器生效**:使用字段映射中定义的 analyzer(如 standard、ik 等)进行文本处理 3. **评分机制**:基于 TF/IDF 或 BM25 算法计算相关性得分 4. **与 Term Query 的区别**: - Term Query:精确匹配未经分析的原始词项 - Match Query:先对输入文本进行分析,再搜索分词后的结果 --- ### 二、基础 DSL 结构 ```json GET /_search { "query": { "match": { "field_name": { "query": "search text", "operator": "and" } } } } ``` --- ### 三、核心参数详解 #### 1. `operator`(逻辑运算符) - **可选值**:`or`(默认) / `and` - **示例**: ```json "match": { "content": { "query": "elasticsearch tutorial", "operator": "and" // 要求同时包含 "elasticsearch" 和 "tutorial" } } ``` #### 2. `fuzziness`(模糊匹配) - 处理拼写错误,支持 `0`、`1`、`2` 或 `auto` - **示例**: ```json "match": { "title": { "query": "elastiksearch", "fuzziness": "auto" // 可匹配 "elasticsearch" } } ``` #### 3. `prefix_length`(模糊控制) - 指定起始字符不变的数量(减少误匹配) - **典型值**:`3`(前 3 个字符必须精确匹配) #### 4. `analyzer`(自定义分析器) - 覆盖字段默认的分析器设置 - **示例**: ```json "match": { "description": { "query": "数据库优化", "analyzer": "ik_max_word" // 使用 ik 分词器处理查询文本 } } ``` --- ### 四、执行流程解析 1. **查询文本处理**: - 通过指定的分析器进行分词 - 生成 token 列表(如 "quick brown" → ["quick", "brown"]) 2. **生成子查询**: - 根据 `operator` 参数生成 `bool` 查询 - 例如 `operator: "and"` 会生成 `must` 组合查询 3. **相关性评分**: - 计算每个匹配文档的 `_score` - 考虑因素:词项频率、逆文档频率、字段长度等 --- ### 五、典型使用场景 1. **搜索引擎式查询**(用户输入自由文本) 2. **模糊匹配需求**(容忍拼写错误) 3. **多词组合查询**(通过 `operator` 控制逻辑) 4. **多语言支持**(配合对应语言的分词器) --- ### 六、进阶技巧 #### 1. 权重控制 (`boost`) ```json "match": { "tags": { "query": "urgent important", "boost": 2.0 // 提高该条件的权重 } } ``` #### 2. 短语匹配 (`match_phrase`) - 需要保持词序时使用 ```json "match_phrase": { "message": "quick brown fox" } ``` #### 3. 多字段查询 (`multi_match`) ```json { "multi_match": { "query": "elasticsearch", "fields": ["title^3", "content"] // title 字段权重 x3 } } ``` --- ### 七、注意事项 1. **避免用于精确值字段**(如 ID、状态码等) 2. **注意分析器一致性**:索引和查询时需使用相同分析器 3. **性能影响**:复杂查询可能影响搜索速度,可结合 `filter` 使用 4. **特殊字符处理**:查询内容中的 `+ - = && || > < !` 等符号需要转义 如果需要更具体的应用场景分析或性能优化建议,可以告诉我您的实际使用需求!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值