当前位置: 首页 > article >正文

ElasticSearch DSL查询之复合查询

复合查询

复合查询概述

复合查询是 Elasticsearch 中用来处理多个查询条件组合的一种方式。在实际的业务场景中,我们往往会面对多条件的查询需求,而这些条件可能是复杂的、组合型的,因此需要通过复合查询来实现。

复合查询主要有两种类型:

  • 基于逻辑运算的复合查询:将多个子查询使用逻辑运算符组合。
  • 影响相关性评分的查询:通过某些方式调整查询文档的相关性评分,以改变文档的排序。



布尔查询(Boolean Query)

布尔查询主要用于根据不同的逻辑条件,组合多个查询子句。常见的逻辑运算符有“与(AND)”、“或(OR)”、“非(NOT)”。在 Elasticsearch 中,布尔查询通过关键字 mustshouldmust_notfilter 来实现这些逻辑运算。

布尔查询的基本结构:

GTE /items/_search {
  "query": {
    "bool": {
      "must": [
        { "match": { "field": "value" } }
      ],
      "should": [
        { "term": { "field": "value" } }
      ],
      "must_not": [
        { "term": { "field": "value" } }
      ],
      "filter": [
        { "range": { "field": { "gte": 10, "lte": 100 } } }
      ]
    }
  }
}
  • must必须匹配,等同于逻辑运算符“与(AND)”,参与评分计算。
  • should可以匹配,等同于逻辑运算符“或(OR)”,参与评分计算。
  • must_not必须不匹配,等同于逻辑运算符“非(NOT)”不参与评分计算。
  • filter过滤条件,与 must 相似,但不参与评分计算。



布尔查询关键字解析

  • must:表示必须满足的条件。多个 must 子查询之间是 与(AND) 的关系,所有条件必须成立,适用于需要“必须满足”的场景。对于需要计算相关性评分的条件,使用 must
  • should:表示可选条件。多个 should 子查询之间是 或(OR) 的关系,至少有一个条件满足时,查询就成功。should 子查询参与评分,但它不是必需的条件,适用于权重较低但仍需匹配的场景。
  • must_not:表示必须不满足的条件。多个 must_not 子查询之间是 与(AND) 的关系,所有条件必须不成立,适用于需要排除某些结果的场景。
  • filter:表示过滤条件,通常用于限制结果的范围(如价格、日期等)。它类似于 must,但是 不参与相关性评分,仅用于过滤结果。适用于那些不需要考虑评分的条件。



filter 的特点

filtermust 都是用来限定结果集的条件,但它们有显著的区别:

  • must:参与评分计算,影响文档排名。
  • filter:不参与评分计算,仅用于过滤。由于不计算评分,它的性能通常更优。



布尔查询实际应用分析

假设我们有一个在线商城,用户进行商品搜索时,输入了关键字“智能手机”,并通过过滤条件选择了品牌为“华为”和价格范围为 900 到 1599 元。我们需要使用布尔查询来处理这个场景。

  • 关键字搜索:用户输入的“智能手机”需要通过全文检索进行匹配。这类查询通常需要计算相关性评分,即匹配度越高的文档越靠前。因此,我们应将其放入 must 中。
  • 品牌过滤:用户选择了品牌为“华为”。品牌过滤通常是一个精确匹配的条件,且不需要计算相关性评分。因此,我们将其放入 filter 中。
  • 价格范围过滤:用户选择了价格范围 900 到 1599 元。与品牌过滤一样,价格范围也是一个精确匹配条件,同样不参与评分,因此也应放入 filter 中。

实际布尔查询语法:

GET /items/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": { 
            "name": "智能手机" 
          }
        }
      ],
      "filter": [
        {
          "term": { 
            "brand": "华为" 
          }
        },
        {
          "range": { 
            "price": { 
              "gte": 90000, 
              "lte": 159900 
            } 
          }
        }
      ]
    }
  }
}
  • match 查询用于处理“智能手机”的模糊匹配
  • term 查询用于处理“品牌”字段的精确匹配
  • range 查询用于处理“价格”范围的筛选

返回结果: 返回条件匹配的记录,并按照评分进行排序。



为何使用 filter 而不是 must

filter 用于那些不需要参与评分的条件。比如品牌和价格范围等条件,它们并不会影响文档的相关性得分,只决定了文档是否匹配,因此使用 filter 可以提高查询效率。相反,must 是用于那些需要计算相关性评分的条件,它会影响查询结果的排名。



总结

布尔查询(Boolean Query)是 Elasticsearch 中非常强大且灵活的查询方式,能够通过逻辑运算符将多个子查询结合起来。常用的布尔查询关键字有:

  • must:用于必须匹配的条件,并参与评分计算。
  • should:用于可选匹配的条件,且影响评分计算。
  • must_not:用于排除的条件。
  • filter:用于过滤的条件,不参与评分计算。

通过合理组合这些关键字,可以实现复杂的查询需求,极大地提高查询的灵活性和性能。

注意事项:

  1. 性能优化:尽量将不参与评分的条件放入 filter 中,避免影响查询效率。
  2. 评分影响:对于需要评分的查询条件,应该使用 mustshould,而不使用 filter
  3. 业务场景分析:在实际应用中,根据业务需求分析条件之间的关系,合理使用 mustshouldmust_notfilter



影响相关性评分的查询

相关性评分概述

在 Elasticsearch 中,相关性评分(Relevance Score)是用于衡量一个文档与查询条件的匹配度的分数,通常用于排序文档。Elasticsearch 使用一种称为 TF-IDF(Term Frequency-Inverse Document Frequency) 的算法来计算相关性评分,另外也使用了 BM25 等改进算法。

相关性评分的计算主要受到以下因素的影响:

  • 词频(TF):查询词在文档中出现的频率。
  • 逆文档频率(IDF):查询词在所有文档中出现的频率,出现频率越低的词对文档的评分影响越大。
  • 文档长度:通常来说,文档越短,匹配度越高。

影响相关性评分的查询方式主要是通过改变查询条件来调整文档的得分。



影响相关性评分的查询类型

影响相关性评分的查询通常依赖于对字段的精确匹配或模糊匹配。常见的影响相关性评分的查询类型有:

  • match 查询:进行全文检索,影响文档的相关性评分。
  • multi_match 查询:用于在多个字段上执行全文检索,影响文档的相关性评分。
  • boost:通过设置权重,增加某些查询条件对相关性评分的影响。



match 查询

match 查询是最常用的影响相关性评分的查询,它会计算查询词在文档中的匹配度,并返回相关性评分。通常,match 查询用于全文检索,文档中的匹配词出现的越多,评分越高。

示例:

GET /indexName/_search
{
  "query": {
    "match": {
      "description": "智能手机"
    }
  }
}

在此查询中,description 字段中包含“智能手机”的文档将会有更高的相关性评分。



multi_match查询

multi_match 查询是一个扩展的 match 查询,可以在多个字段中执行全文检索。它与多个 match 查询类似,但只需要编写一个查询条件即可应用于多个字段。

示例:

GET /indexName/_search
{
  "query": {
    "multi_match": {
      "query": "智能手机",
      "fields": ["title", "description", "content"]
    }
  }
}

在这个例子中,查询会在 titledescriptioncontent 三个字段中查找包含“智能手机”的文档,并根据字段匹配度进行相关性评分。



boost设置

通过 boost 参数可以增强某些查询条件对相关性评分的影响。boost 是一个浮动系数,表示该查询条件相对于其他条件的权重。

示例:

GET /indexName/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "智能手机",
              "boost": 2
            }
          }
        },
        {
          "match": {
            "description": "智能手机"
          }
        }
      ]
    }
  }
}

在此查询中,title 字段的匹配结果会被加权处理,相对于 description 字段的匹配结果 ,其得分为 (boost 值的)两倍。



影响评分的其他查询类型

除了上述常见的查询方式,还有一些查询可以直接或间接地影响相关性评分,主要包括:

  • term 查询:精确匹配某个字段的值。虽然 term 查询通常不参与评分计算,但在某些情况下,它可以与其他查询结合,间接影响文档的排序。
  • range 查询:根据字段的范围来过滤文档,range 查询本身不会直接影响评分,但可以通过与 mustshould 结合使用,间接调整评分。
  • function_score 查询:允许用户通过自定义函数对文档的相关性评分进行调整,可以结合查询结果和外部因素来进行评分计算。


function_score查询

function_score 查询允许开发者通过自定义的函数对查询结果的评分进行修改。可以使用不同的评分函数(如权重、衰减函数、随机函数等)来影响文档的最终评分。

示例:

GET /indexName/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { 
          "description": "智能手机" 
        }
      },
      "boost_mode": "multiply",
      "functions": [
        {
          "gauss": {
            "price": {
              "origin": "1000",
              "scale": "500",
              "offset": "0",
              "decay": 0.5
            }
          }
        }
      ]
    }
  }
}
  • function_score 查询:这部分会基于查询的结果修改文档的评分。它接收一个查询和一个或多个评分函数,在这个例子中有一个评分函数是 gauss
  • boost_mode: "multiply":这个选项表示查询的原始相关性评分(来自 match 查询)将与函数评分结果相乘。这意味着如果函数评分较高,文档的总评分会被放大,影响其在结果中的排名。
  • functions 部分:
    • gauss 函数是一个常用的数学函数,通常用来对某些字段(比如 price)进行评分调整。
    • price 字段表示的是文档的价格。gauss 函数的作用是根据价格的值来对文档的评分进行调整。
      • origin: "1000":这是函数的起始值,即价格为 1000 时,评分的衰减(Decay)开始。
      • scale: "500":这是衰减的范围。当价格偏离 1000 达到 500 时,评分会降低。
      • offset: "0":这个参数表示从 1000 开始,计算衰减的“偏移量”,通常设置为0。
      • decay: 0.5:这个参数决定了衰减的速率。衰减越快,价格越高的文档评分会降低得越快。

结果是:

  • match 查询会根据 description 字段中与“智能手机”的匹配程度来评分文档。
  • gauss 函数会根据文档中的 price 字段的值来调整评分。价格接近1000的文档会有更高的评分,价格偏离1000的文档评分会降低。
  • 最终,两个评分(来自 matchgauss)会通过 boost_mode: "multiply" 进行相乘,影响文档的最终评分。



dis_max查询

dis_max 查询允许我们根据多个查询结果返回得分最高的一个,通常用于组合多个查询条件。它会选择所有查询中得分最高的一个,并返回该文档。这个查询适用于某些场景下,想要从多个查询条件中选择最匹配的一个。

示例:

GET /indexName/_search
{
  "query": {
    "dis_max": {
      "queries": [
        { 
          "match": { 
            "title": "智能手机" 
          } 
        },
        { 
          "match": 
          { 
            "description": "智能手机" 
          } 
        }
      ],
      "tie_breaker": 0.7
    }
  }
}

dis_max 查询的核心组成部分:

  • queries:这是一个数组,里面包含了多个查询。在这个例子中,有两个 match 查询:
    • match 查询在 title 字段中查找“智能手机”。
    • match 查询在 description 字段中查找“智能手机”。
  • tie_breaker:这个参数用于控制当多个查询的相关性评分差距较小(即评分接近时)如何合并它们的评分。如果 tie_breaker 为 0(默认值),那么 dis_max 查询只会选择评分最高的查询结果。如果设置为一个值(例如 0.7),则当多个查询的评分相近时,它们的相关性评分会按比例合并,tie_breaker 表示合并的权重。



总结

影响相关性评分的查询是 Elasticsearch 中用于调整和优化查询结果排序的重要工具。通过合理使用以下查询类型,可以极大地提高查询的精准度和业务需求的匹配度:

  • match multi_match 查询:用于全文检索,影响评分计算。
  • boost:通过权重调整查询条件对评分的影响。
  • function_score 查询:自定义评分函数,灵活调整文档得分。
  • dis_max 查询:选择多个查询结果中得分最高的一个,适用于多条件匹配。

通过结合使用这些查询类型,可以灵活地优化文档的排序和相关性评分,使查询结果更加符合用户的需求。


注意事项:

  1. 避免过度使用 boost:虽然 boost 可以增加某些条件的权重,但过多使用可能导致其他条件的权重过低,从而影响查询的合理性。
  2. 调整评分函数时要小心:使用 function_score 时,确保函数的设计符合业务需求,避免因过度复杂的评分函数导致性能问题。
  3. 性能优化:影响评分的查询会增加计算复杂度,在大量文档的查询场景中,应谨慎使用复杂的查询函数,确保查询效率。

http://www.kler.cn/a/509177.html

相关文章:

  • SpringBoot2 + Flowable(UI)
  • 【Java】LinkedHashMap (LRU)淘汰缓存的使用
  • 基于 Python 的深度学习的车俩特征分析系统,附源码
  • 【从0带做】基于Springboot3+Vue3的心理健康预约平台
  • Python GUI Pyside6 实例笔记
  • 计算机网络常见协议
  • CTK插件框架学习-源码下载编译(01)
  • 第29周:文献阅读
  • HTML应用指南:利用GET请求获取全国特斯拉充电桩位置
  • 线程池的数据结构是什么 为什么会占用堆内存 线程池是一个对象吗
  • 算法练习——链表
  • YOLOv8改进,YOLOv8检测头融合RepConv卷积,并添加小目标检测层(四头检测),适合目标检测、分割等
  • 基于微信小程序的驾校预约管理系统设计与实现(LW+源码+讲解)
  • Linux中关闭SSH的DNS解析
  • 03-最长回文子串
  • 创建NFS共享目录
  • day25_HTML
  • Linux下扫描SMB及445漏洞的实用命令与工具详解
  • Windows下的C++内存泄漏检测工具Visual Leak Detector (VLD)介绍及使用
  • mysql打开报错fail to connecto to mysql at 127.0.0.1:3306 with user root
  • Ei Scopus双检索 | 2025年第五届机器人与人工智能国际会议(JCRAI 2025)
  • 前端——Html+CSS
  • Chrome谷歌浏览器如何能恢复到之前的旧版本
  • 防止 SQL 注入的技术文档
  • C#枚举类型携带额外数据的方法
  • 正点原子repo放到自己的git服务器