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

掌握ElasticSearch(七):相关性评分

文章目录

  • 一、Elasticsearch的打分机制
    • 1.TF-IDF
      • TF-IDF 概述
      • 基本公式
      • 示例
    • 2.BM25
      • BM25 概述
      • 配置参数
  • 二、boosting调整打分
    • 1. `match` 查询
    • 2. `multi_match` 查询
    • 3. `bool` 查询
    • 4. `boosting` 查询
    • 5.动态 Boosting
  • 三、Elasticsearch的查询再打分策略
    • 查询阶段(Query Phase)
    • 取回和打分阶段(Fetch and Score Phase)
  • 四、function_score定制得分
    • 内置评分函数
    • 基本语法
    • 参数说明
  • 五、explain API
    • 基本用法
    • 解释结果结构
    • 示例
    • 解释结果示例
    • 解释结果的详细说明
    • 常见用途

一、Elasticsearch的打分机制

Elasticsearch提供了一个强大的全文搜索能力,并且能够实时处理大量的数据。在 Elasticsearch 中,文档的打分(Scoring)机制是基于 TF/IDF 模型(Term Frequency/Inverse Document Frequency),以及 BM25(Best Matching 25)算法来计算文档的相关性。

1.TF-IDF

TF-IDF 概述

TF-IDF(Term Frequency-Inverse Document Frequency,词频-逆文档频率)是一种常用的统计方法,用于评估一个词对文档或语料库的重要程度。这种方法结合了两个指标:

  1. TF (Term Frequency, 词频):一个词在文档中出现的频率。
  2. IDF (Inverse Document Frequency, 逆文档频率):一个词在整个文档集合中出现的频率的倒数,用来衡量这个词的独特性。

基本公式

在这里插入图片描述

示例

假设有一个简单的索引,包含以下三个文档:

  • 文档 A: “猫 狗 鱼”
  • 文档 B: “猫 猫 猫 狗”
  • 文档 C: “狗 鱼”

如果用户搜索关键词 “猫”,Elasticsearch 会计算每个文档中 “猫” 的 TF-IDF 分数,并根据这些分数对文档进行排序。

  • 文档 A 中 “猫” 的 TF-IDF 分数:

在这里插入图片描述

  • 文档 B 中 “猫” 的 TF-IDF 分数:

在这里插入图片描述

  • 文档 C 中 “猫” 的 TF-IDF 分数:

在这里插入图片描述

根据这些分数,文档 B 会被排在文档 A 之前,因为 “猫” 在文档 B 中的 TF-IDF 分数更高。

2.BM25

BM25(Best Matching 25)是一种广泛使用的排名函数,用于信息检索领域,特别是在搜索引擎中。相比传统的 TF-IDF 方法,BM25 更加准确地反映了文档与查询之间的相关性,尤其是在处理短查询和长文档时表现更佳。

BM25 概述

BM25 的评分公式如下:

在这里插入图片描述

其中:

在这里插入图片描述

在这里插入图片描述

配置参数

  • 可以通过设置索引的 index.similarity.default 参数来调整 BM25 的参数:
    PUT /my-index
    {
      "settings": {
        "index": {
          "similarity": {
            "default": {
              "type": "BM25",
              "k1": 1.2,
              "b": 0.75
            }
          }
        }
      }
    }
    

二、boosting调整打分

在 Elasticsearch 中,boosting 是一种用于调整查询中各个部分权重的技术。通过 boosting,可以提高或降低某些查询条件的重要性,从而影响最终的搜索结果排序。boosting 可以应用于单个查询子句,也可以应用于整个查询。

  1. Boost 值:一个正数,表示查询子句的重要性。默认值为 1.0。值越大,查询子句在最终评分中的权重越高。
  2. Positive Query:主查询,用于匹配文档并计算基础评分。
  3. Negative Query:可选的负查询,用于减少某些文档的评分。

1. match 查询

match 查询是最常见的全文搜索查询,可以使用 boost 参数来调整匹配项的权重。

GET /my-index/_search
{
  "query": {
    "match": {
      "title": {
        "query": "Elasticsearch",
        "boost": 2.0
      }
    }
  }
}

在这个例子中,标题中包含 “Elasticsearch” 的文档的评分将乘以 2.0。

2. multi_match 查询

multi_match 查询允许在多个字段中进行搜索,并可以为每个字段设置不同的 boost 值。

GET /my-index/_search
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch",
      "fields": [
        "title^2.0",
        "content^1.5",
        "tags^1.0"
      ]
    }
  }
}

在这个例子中,标题字段的匹配项权重是内容字段的两倍,标签字段的匹配项权重最低。

3. bool 查询

bool 查询允许组合多个查询子句,并可以为每个子句设置 boost 值。

GET /my-index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "Elasticsearch",
              "boost": 2.0
            }
          }
        },
        {
          "match": {
            "content": {
              "query": "Elasticsearch",
              "boost": 1.5
            }
          }
        }
      ]
    }
  }
}

在这个例子中,标题字段的匹配项权重是内容字段的 1.33 倍。

4. boosting 查询

boosting 查询允许你指定一个正查询和一个负查询,并通过 negative_boost 参数调整负查询的影响。

GET /my-index/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "title": "Elasticsearch"
        }
      },
      "negative": {
        "match": {
          "content": "outdated"
        }
      },
      "negative_boost": 0.2
    }
  }
}

在这个例子中,标题中包含 “Elasticsearch” 的文档会被优先返回,但如果内容中包含 “outdated”,这些文档的评分会被显著降低。

5.动态 Boosting

除了静态设置 boost 值,Elasticsearch 还支持动态调整 boost 值。这可以通过使用脚本评分 (script_score) 来实现。

GET /my-index/_search
{
  "query": {
    "script_score": {
      "query": {
        "match": {
          "title": "Elasticsearch"
        }
      },
      "script": {
        "source": "_score * doc['popularity'].value"
      }
    }
  }
}

在这个例子中,文档的最终评分是原始评分乘以 popularity 字段的值。

三、Elasticsearch的查询再打分策略

在 Elasticsearch 中,“查询后再打分”(Query Then Fetch and Score)是一种优化查询性能的策略。这种策略分为两个阶段:首先是查询阶段(Query Phase),然后是取回和打分阶段(Fetch and Score Phase)。下面详细介绍这两个阶段的工作原理和优化效果。

查询阶段(Query Phase)

  1. 分布式查询

    • 当用户提交一个查询请求时,Elasticsearch 会将查询请求广播到所有相关的分片(shards)。
    • 每个分片独立执行查询,并生成一个初步的匹配文档列表(通常是前 K 个文档)。
  2. 局部评分

    • 每个分片会对匹配的文档进行初步评分,计算出每个文档的相关性得分。
    • 这些评分是基于分片内的数据进行的,因此可能会有一些偏差。
  3. 汇总结果

    • 每个分片将初步评分的前 K 个文档的结果发送回协调节点(coordinating node)。
    • 协调节点收集所有分片的结果,并进行全局排序,选出最终的前 N 个文档。

取回和打分阶段(Fetch and Score Phase)

  1. 文档取回

    • 协调节点从每个分片中取回初步筛选出的文档的完整内容。
    • 这一步骤是为了获取文档的详细信息,以便进行进一步的评分和处理。
  2. 全局评分

    • 协调节点对取回的文档进行全局评分。这一步骤可能包括重新计算评分、应用额外的评分因子(如动态 boosting)等。
    • 全局评分确保了最终结果的准确性,因为它考虑了所有分片的数据。
  3. 最终排序

    • 协调节点根据全局评分对文档进行最终排序,生成最终的搜索结果。
    • 最终结果按评分高低返回给用户。
  • 优化效果:
  1. 减少网络传输

    • 通过在每个分片上进行初步筛选和评分,减少了需要传输的文档数量,从而降低了网络带宽的消耗。
  2. 提高响应速度

    • 分布式查询和并行处理提高了查询的响应速度,尤其是在处理大规模数据集时。
  3. 减少资源消耗

    • 只有初步筛选出的文档才会被取回和重新评分,减少了计算资源的消耗。

“查询后再打分”策略通过分阶段处理查询请求,有效地提高了查询性能和响应速度。通过在分片上进行初步筛选和评分,减少了网络传输和资源消耗,确保了最终结果的准确性和可靠性。这种策略特别适合处理大规模数据集和复杂查询场景。

四、function_score定制得分

function_score 查询是 Elasticsearch 中一种强大的工具,用于在查询过程中动态地调整文档的评分。通过 function_score,我们可以根据自定义的评分函数来修改文档的默认评分,从而更精细地控制搜索结果的排序。

  1. 评分函数:用于计算文档的新评分的函数。Elasticsearch 提供了多种内置的评分函数,也可以使用自定义脚本。
  2. 过滤器:用于限制哪些文档应该应用评分函数。
  3. Boost 模式:定义如何将评分函数的结果与默认评分相结合。

内置评分函数

Elasticsearch 提供了多种内置的评分函数,包括但不限于:

  1. weight:简单地为文档添加一个固定的权重。
  2. random_score:为文档分配一个随机评分。
  3. field_value_factor:根据文档中的某个字段值来调整评分。
  4. linear:线性插值函数。
  5. exp:指数衰减函数。
  6. gauss:高斯衰减函数。
  7. script_score:使用自定义脚本计算评分。

基本语法

GET /my-index/_search
{
  "query": {
    "function_score": {
      "query": { 
        "match": { "title": "Elasticsearch" }
      },
      "functions": [
        {
          "filter": { "term": { "status": "active" } },
          "weight": 2
        },
        {
          "field_value_factor": {
            "field": "popularity",
            "factor": 1.2,
            "modifier": "sqrt",
            "missing": 1
          }
        }
      ],
      "boost_mode": "multiply",
      "score_mode": "sum",
      "max_boost": 10,
      "min_score": 1
    }
  }
}

参数说明

  1. query:基础查询,用于匹配文档并计算初始评分。
  2. functions:一个数组,包含一个或多个评分函数及其过滤器。
  3. boost_mode:定义如何将评分函数的结果与默认评分相结合。可选值包括:
    • multiply:乘法模式,将评分函数的结果乘以默认评分。
    • replace:替换模式,直接使用评分函数的结果作为最终评分。
    • sum:求和模式,将评分函数的结果加到默认评分上。
    • avg:平均模式,取评分函数的结果和默认评分的平均值。
    • max:最大值模式,取评分函数的结果和默认评分的最大值。
    • min:最小值模式,取评分函数的结果和默认评分的最小值。
  4. score_mode:定义如何将多个评分函数的结果组合在一起。可选值包括:
    • multiply:乘法模式。
    • sum:求和模式。
    • avg:平均模式。
    • first:使用第一个评分函数的结果。
    • max:最大值模式。
    • min:最小值模式。
  5. max_boost:设置评分的最大值。
  6. min_score:设置评分的最小值,低于此值的文档将被过滤掉。

五、explain API

Elasticsearch 的 explain API 用于获取关于特定文档为何被查询命中的详细信息,包括评分计算的细节。这对于调试和优化查询非常有用,可以帮助我们理解查询是如何工作的,以及为什么某些文档的评分高于其他文档。

  1. 解释结果explain 返回一个详细的 JSON 结构,描述了查询的每个部分如何影响文档的评分。
  2. 评分细节:包括每个评分组件的值、匹配条件、以及是否满足这些条件。
  3. 调试工具:帮助开发者和管理员理解查询的内部工作原理,从而优化查询性能和结果质量。

基本用法

要使用 explain API,需要指定索引名称、文档 ID 和查询条件。以下是一个基本示例:

GET /my-index/_explain/1
{
  "query": {
    "match": {
      "title": "Elasticsearch"
    }
  }
}

在这个例子中,my-index 是索引名称,1 是文档 ID,查询条件是匹配 title 字段中包含 “Elasticsearch” 的文档。

解释结果结构

explain API 返回的 JSON 结构包含多个字段,以下是一些主要字段的解释:

  1. _index:文档所在的索引名称。
  2. _type:文档的类型(在 Elasticsearch 7.x 及以上版本中,类型已被移除)。
  3. _id:文档的 ID。
  4. matched:布尔值,表示文档是否匹配查询。
  5. explanation:包含评分计算的详细信息。
    • value:文档的最终评分。
    • description:评分计算的描述。
    • details:包含子评分组件的详细信息。

示例

假设我们有一个索引 my-index,包含以下文档:

PUT /my-index/_doc/1
{
  "title": "Elasticsearch in Action",
  "content": "Learn how to use Elasticsearch effectively.",
  "popularity": 50
}

PUT /my-index/_doc/2
{
  "title": "Introduction to Search Engines",
  "content": "An overview of search engines and their components.",
  "popularity": 30
}

我们执行一个 explain 请求来查看文档 1 为何被查询命中:

GET /my-index/_explain/1
{
  "query": {
    "match": {
      "title": "Elasticsearch"
    }
  }
}

解释结果示例

{
  "_index": "my-index",
  "_type": "_doc",
  "_id": "1",
  "matched": true,
  "explanation": {
    "value": 1.2038395,
    "description": "weight(title:Elasticsearch in 0) [PerFieldSimilarity], result of:",
    "details": [
      {
        "value": 1.2038395,
        "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:",
        "details": [
          {
            "value": 0.6931472,
            "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
            "details": [
              {
                "value": 1.0,
                "description": "docFreq",
                "details": []
              },
              {
                "value": 2.0,
                "description": "docCount",
                "details": []
              }
            ]
          },
          {
            "value": 1.7364818,
            "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
            "details": [
              {
                "value": 1.0,
                "description": "freq, occurrences of term within document",
                "details": []
              },
              {
                "value": 1.2,
                "description": "k1, term saturation parameter",
                "details": []
              },
              {
                "value": 0.75,
                "description": "b, length normalization parameter",
                "details": []
              },
              {
                "value": 16.0,
                "description": "dl, length of field",
                "details": []
              },
              {
                "value": 16.0,
                "description": "avgdl, average length of field",
                "details": []
              }
            ]
          }
        ]
      }
    ]
  }
}

解释结果的详细说明

  1. _index:文档所在的索引名称,这里是 my-index
  2. _type:文档的类型,这里是 _doc
  3. _id:文档的 ID,这里是 1
  4. matched:布尔值,表示文档是否匹配查询,这里是 true
  5. explanation
    • value:文档的最终评分,这里是 1.2038395
    • description:评分计算的描述,这里是 weight(title:Elasticsearch in 0) [PerFieldSimilarity], result of:
    • details:包含子评分组件的详细信息,例如 idftf 的计算过程。

常见用途

  1. 调试查询:帮助我们理解为什么某些文档被匹配,而其他文档没有被匹配。
  2. 优化评分:通过查看评分计算的细节,可以调整查询参数或评分函数,以优化搜索结果的质量。
  3. 性能分析:了解查询的性能瓶颈,优化查询性能。

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

相关文章:

  • 实际案例说明用基于FPGA的原型来测试、验证和确认IP——如何做到鱼与熊掌兼得?
  • 区块链底层协议比较#DAPP开发
  • 《华为工作法》读书摘记
  • 【鸿蒙新闻】10月29日警用鸿蒙开发者大会在北京胜利召开,开启智慧应用新时代!
  • 怎么安装行星减速电机才是正确的
  • 实体类中为什么要实现serializable接口
  • Axios-Mock-Adapter mock数据
  • 《卷积、卷积操作、卷积神经网络原理探索》
  • 3. 探索 Netty 的粘包与拆包解决方案
  • ARM base instruction -- mneg
  • 正点原子阿尔法ARM开发板-IMX6ULL(十一)——IIC协议和SPI协议--AP3216C环境光传感器和ICM20608六轴传感器
  • 在Zetero中调用腾讯云API的输入密钥的问题
  • 【Linux】信号三部曲——产生、保存、处理
  • ES跟Kafka集成
  • git 切换分支
  • 一个运维牛人对运维规则的10个总结
  • 秒懂Linux之Socket编程(四)
  • 支持向量机SVM与自然语言处理基础小结
  • 2024.10.2校招 实习 内推 面经
  • 函数基础,定义与调用。作用域,闭包函数
  • 升序数组两两不相等
  • C语言稀有关键词:柔性数组
  • 【创建型】单例模式
  • Hypack 应用于地形测量的高级设置操作要领
  • Nginx 的 Http 模块介绍(上)
  • Git - 两种方式撤销已提交到远端仓库的记录并删除提交记录