Elasticsearch Query DSL 整理总结(三)—— Match Phrase Query 和 Match Phrase Prefix Query

引言

今天再读庄子的《逍遥游》,其中鲲鹏之扶摇直上九万里之气势,蜩(tiao)与学鸠之渺小之对比,令人印象深刻,并对鲲鹏之志心生向往。而郭象在注《庄子》卷中却说,"苟足于其性,则虽大鹏无以自贵于小鸟,小鸟无羡于天池,而荣愿有余矣。故小大虽殊,逍遥一也。"观看自身,虽然不是什么领导,老总,但也完全不必感到为职业生涯忧虑,只要热爱程序员这个工作,享受编码的乐趣,做到 80 岁又有何妨。

书归正传,今天我们聊聊 Match Phase Query。

Match Phase Query

match_phrase 查询针对的是一个语句,比如 "like football", 分析时也会将整个语句作为整体,而不会像上篇的 match 查询 会将整个语句拆分为单个词条。

举个例子,创建一个 match_phase type 并塞进去一个文档, message 是 I like swimming and riding!

PUT matchphasetest
{}

PUT matchphasetest/_mapping/match_phase
{
  "properties": {
    "message": {
      "type": "text"
    }
  }
}

PUT matchphasetest/match_phase/1
{
  "message": "I like swimming and riding!"
}

GET matchphasetest/_search
{
  "query": {
    "match_phrase": {
      "message": "I like swimming"
    }
  }
}

默认使用 match_phrase 时会精确匹配查询的短语,需要全部单词和顺序要完全一样,标点符号除外。

slop 参数

这种精确匹配在大部分情况下显得太严苛了,有时我们想要包含 ""I like swimming and riding!"" 的文档也能够匹配 "I like riding"。这时就要以用到 "slop" 参数来控制查询语句的灵活度。

slop 参数告诉 match_phrase 查询词条相隔多远时仍然能将文档视为匹配 什么是相隔多远? 意思是说为了让查询和文档匹配你需要移动词条多少次?

以 "I like swimming and riding!" 的文档为例,想匹配 "I like riding",只需要将 "riding" 词条向前移动两次,因此设置 slop 参数值为 2, 就可以匹配到。

GET matchphasetest/_search
{
  "query": {
    "match_phrase": {
      "message": {
        "query": "I like riding",
        "slop": 2
      }
    }
  }
}

analyzer 参数

match_phrase 语句也可以设置 analyzer 参数来定义查询语句时对其中词条执行的分析过程。

默认情况下,使用的是创建 mapping 时的分析器,如果没有指定就会使用默认的查询分析器。这里举个例子(只是如何使用)

GET /_search
{
    "query": {
        "match_phrase" : {
            "message" : {
                "query" : "this is a test",
                "analyzer" : "my_analyzer"
            }
        }
    }
}

zero terms query

match_phrase 也接受 zero_terms_query 为参数,使用方式和 match查询语句相同

Match Phrase 前缀查询

match_phrase_prefixmatch_phrase 用法是一样的,区别就在于它允许对最后一个词条前缀匹配。以上节的数据为例,查询 I like sw 就能匹配到

I like swimming and riding

GET matchphasetest/_search
{
  "query": {
    "match_phrase_prefix": {
      "message": "I like swi"
    }
  }
}

max_expansions

官方文档中说 match_phrase_prefix 查询中有个参数 max_expansions 说的是参数 max_expansions 控制着可以与前缀匹配的词的数量,默认值是 50。

I like swi 查询为例,它会先查找第一个与前缀 swi 匹配的词,然后依次查找搜集与之匹配的词(按字母顺序),直到没有更多可匹配的词或当数量超过 max_expansions 时结束。

但是我在使用时,故意造出了数十个以 swi 开头的词,而将 max_expansions 的值设为 10。但是却返回了所有的结果。在 elasitc 官网也有对该问题的讨论, 也是没有找到答案。这个问题作为一个公案权且记下,如果您知道原因,麻烦告诉我,非常感谢。

这里也贴出个例子,以备后面排查

GET matchphaseprefixtest/_search
{
  "query": {
    "match_phrase_prefix": {
      "message": {
        "query": "I like sw",
        "max_expansions": 10
       }
    }
  }
}

match_phrase_prefix 用起来非常方便,能够实现输入即搜索的效果,但是也会出现问题。 假如说查询 I like s 并且想要匹配 I like swimming ,结果是默认情况下它会搜索出前 50 个组合,如果前 50 个没有 swimming ,那就不会显示出结果。只能是用户继续输入后面的字母才可能匹配出结果。

要实现更好的即使搜索的特性,可以看看 completion suggester
Index-Time Search-as-You-Type 能不能实现。

小结

本文论述了 Match Phase Query 和 Match Phrase 前缀查询 的使用,下文会讲解 Multi Match Query 敬请期待。

参考文档

1.Match Phrase Query

系列文章列表

Query DSL

  1. Query DSL 概要,MatchAllQuery,全文查询简述
  2. Match Query

Java Rest Client API

  1. Elasticsearch Java Rest Client API 整理总结 (一)——Document API
  2. Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI
  3. Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries

转载于:https://www.cnblogs.com/reycg-blog/p/10012238.html

<think>嗯,用户想了解ElasticsearchQuery DSL使用方法及示例。首先,我需要回忆一下Elasticsearch的查询类型,记得有Term-level查询全文查询两大类。Term-level用于精确匹配,比如keyword字段,而全文查询则会用到分词器,适用于text类型的字段。 用户可能不太清楚这两者的区别,所以需要先解释清楚。然后,常见的查询类型比如term、match、range、bool这些应该都是基础且常用的,需要给出每个的示例。比如term查询是精确匹配,而match会进行分词处理。 还要注意用户提供的引用内容,他们提到了Term level queriesprefix、regexp的例子,所以在回答中要涵盖这些。可能需要分点介绍不同的查询类型,每个类型给出一个示例,并说明使用场景。 另外,用户可能希望看到实际的JSON结构示例,这样更容易理解如何构造查询。比如term查询的结构,或者bool查询如何组合多个条件。同时,要提到如何在实际代码中执行这些查询,比如使用Java High Level REST Client,如引用中的SearchResponsesearchRequest的用法。 还要考虑用户的实际应用场景,比如日志分析、商品搜索,这样举例会更贴近实际需求。最后,生成的相关问题需要引导用户进一步学习,比如如何优化查询性能,或者如何处理复杂查询组合。 需要检查是否有遗漏的查询类型,确保覆盖主要的查询方式,同时保持结构清晰,步骤明确。可能还需要提醒用户注意字段类型的影响,比如textkeyword的区别,避免常见的错误用法。</think>### Elasticsearch Query DSL 使用方法及示例 Elasticsearch Query DSL(领域特定语言)提供了灵活的搜索条件定义方式,可分为**Term-level查询**(精确匹配)**全文查询**(分词匹配)两类[^1][^2]。以下是核心功能及示例: --- #### 一、基础查询类型 1. **Term 查询** 精确匹配字段值,适用于`keyword`类型字段: ```json { "query": { "term": { "status": "published" // 完全匹配"published"的文档 } } } ``` 2. **Match 查询** 对`text`类型字段进行分词搜索: ```json { "query": { "match": { "content": "搜索引擎原理" // 拆分为"搜索引擎"、"原理"进行匹配 } } } ``` 3. **Range 查询** 数值/日期范围筛选: ```json { "query": { "range": { "price": { "gte": 100, "lte": 500 } } } } ``` --- #### 二、复合查询 1. **Bool 查询** 组合多个查询条件: ```json { "query": { "bool": { "must": [ // 必须满足 { "match": { "title": "手机" } } ], "filter": [ // 过滤条件(不计分) { "range": { "stock": { "gt": 0 } } } ] } } } ``` 2. **Prefix 查询** 前缀匹配(适合自动补全场景): ```json { "query": { "prefix": { "user.name": "zhang" // 匹配"zhangsan"等 } } } ``` --- #### 、实战示例(日志分析) 查找2023年包含"error"且来自"server-01"的日志: ```json { "query": { "bool": { "must": [ { "match": { "message": "error" } }, { "term": { "hostname": "server-01" } } ], "filter": [ { "range": { "@timestamp": { "gte": "2023-01-01" } } } ] } } } ``` --- #### 四、Java客户端调用示例 ```java SearchRequest searchRequest = new SearchRequest("logs"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.termQuery("level", "error")); searchRequest.source(sourceBuilder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // ``` --- ### 应用场景建议 1. **电商搜索**:组合`match`(商品名称)、`range`(价格区间)、`term`(分类) 2. **日志分析**:使用`bool`+`range`进行时间范围过滤 3. **内容平台**:`match_phrase`实现精准短语匹配 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值