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

重生之我们在ES顶端相遇第 19 章 - 综合排序(进阶),打造你的个性化排序

文章目录

      • 0. 前言
      • 1. Function score query 是什么
      • 2. field_value_factor 基本使用
        • 2.1 查询例子
        • 2.2 算分解释
        • 2.3 参数说明
      • 3. random_score 基本使用
        • 3.1 查询例子
        • 3.2 参数说明
      • 4. weight、script_score
      • 5. 衰退函数
        • 5.1 gauss
          • 5.1.1 主要参数
          • 5.1.2 查询例子
        • 5.2 exp
        • 5.3 linear

0. 前言

假设有这样一个业务场景:
如何实现类似电商搜索按照价格、销量、评分等因素的实时综合排序?

要实现这样的功能,就需要引出我们的主角了:Function score query

1. Function score query 是什么

Function score query 主要用于修改文档的算分场景,在开发中使用频率非常高。
该查询 API, 有以下参数:

  1. query
    • 作用: 定义要过滤和被修改评分的文档。可以是任何有效的查询
  2. boost
    • 描述: 浮点数值,用于调整文档得分
    • 作用: 修改所有返回文档的得分
  3. functions
    • 描述: 函数数组,定义如何调整得分
    • 作用: functions 中的每个函数都可修改文档得分,包括以下函数
      • weight: 给文档加权重
      • random_score: 使用随机值调整得分
      • field_value_factor: 基于文档字段值计算得分
      • script_score: 使用脚本计算得分
      • decay functions: 使用算法(如 exp, linear, gauss)针对某个字段的值进行衰退。
  4. score_mode:
    • 作用: 如何组合多个函数的得分。可选值包括
      • sum: 所有函数得分相加
      • multiply: 所有函数得分相乘
      • first: 只使用第一个函数的得分
      • max: 取最大得分
      • min: 取最小得分
  5. boost_mode:
    • 作用: 定义文档原始得分与函数得分的组合方式。可选值包括
      • replace: 使用函数得分替代原始得分
      • sum: 函数得分 + 原始得分
      • multiply: 函数得分 * 原始得分
      • max: max(函数得分,原始得分)
      • avg: 取均值
      • min: min(函数得分,原始得分)
  6. min_score:
    • 作用: 浮点值,只返回得分高于该值的文档
  7. max_boost:
    • 描述: 浮点数值,限制文档的最大得分

下面,我将通过具体例子的方式,带大家了解使用

2. field_value_factor 基本使用

2.1 查询例子

写入测试数据

POST /_bulk
{"index": {"_index":"test_19","_id": "1"}}
{"shopName":"elasticsearch","sales_volume": 2134,"score": 3.3}
{"index": {"_index":"test_19","_id": "2"}}
{"shopName":"java","sales_volume": 124912,"score": 4.9}
{"index": {"_index":"test_19","_id": "3"}}
{"shopName":"golang","sales_volume": 34352,"score": 4.2}
{"index": {"_index":"test_19", "_id": "4"}}
{"shopName":"nodejs","sales_volume": 7545,"score": 5.0}
{"index": {"_index":"test_19", "_id": "5"}}
{"shopName":"rust","sales_volume": 31221,"score": 5.0}

查询

GET test_19/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": """
              if (doc['sales_volume'].value < 10) {
                return _score * 0.1
              } else if (doc['sales_volume'].value < 100) {
                return _score * 2
              } else if (doc['sales_volume'].value < 1000) {
                return _score * 3
              } else if (doc['sales_volume'].value < 10000) {
                return _score * 4
              } else {
                return _score * 5
              }
            """
          },
          "weight": 2
        },
        {
          "field_value_factor": {
            "field": "score",
            "factor": 1.5,
            "modifier": "sqrt",
            "missing": 1
          },
          "weight": 3
        }
      ],
      "min_score": 2,
      "max_boost": 3.5,
      "score_mode": "avg",
      "boost_mode": "multiply"
    }
  }
}
2.2 算分解释

score_mode=avg 算出来的得分为:
score1 = (score(script_score) * weight(2) + score(field_value_factor) * weight(3)) / (weight(2) + weight(3))
注意,这里除的是 2 个函数的 weight 相加值,默认 weight = 1
boost_mode=multiply 算出来的文档最终得分为:
最终得分 = score1 * 文档原始得分

其中 field_value_factor 函数的算分如下:
sqrt(doc['score'].value * 1.5)

2.3 参数说明
  • field: 文档字段
  • factor: 乘以 field 的因子,默认 1
  • modifier: 使用的函数,有以下值:none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, reciprocal,默认为 none
  • missing:field 缺失时的默认值

3. random_score 基本使用

3.1 查询例子
GET test_19/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "random_score": {
            "seed": 2,
            "field": "shopName.keyword"
          }
        }
      ],
      "boost_mode": "replace"
    }
  } 
}
3.2 参数说明
  • seed: 随机数种子
  • field: 不能使用 text 字段,当 seed, field 相同时,同一个查询条件下,随机值会一致

4. weight、script_score

在介绍 field_value_factor 时,已经介绍了 weightscript_score 不再过多介绍。

5. 衰退函数

根据某个值,来降低文档的得分。

5.1 gauss

gauss 衰退函数使用正态分布(高斯分布)来计算得分衰退。得分从一个最大值开始,随着距离的增加(或时间的推移)而逐渐降低。

5.1.1 主要参数
  1. origin
    • 作用: 确定得分的起点,以该值向两边衰退。该值一般为 数字、时间、地理坐标
  2. scale
    • 作用: 衰退的范围,决定得分下降的速度。在范围内得分会相对较高
  3. offset(可选)
    • 作用: 在偏离 origin 多少 offset 范围内,得分不会降低
5.1.2 查询例子
PUT test_19_decay
{
  "mappings": {
    "properties": {
      "location": {
         "type": "geo_point"
      },
      "name": {
        "type": "keyword"
      },
      "score": {
        "type": "double"
      }
    }
  }
}
PUT /_bulk
{"index": {"_index":"test_19_decay","_id": "1"}}
{"name":"elasticsearch","location": {"lon": -71.34,"lat": 41.12}, "score": 3.2}
{"index": {"_index":"test_19_decay","_id": "2"}}
{"name":"java","location": {"lon": 123.21,"lat": 21.21},"score": 4.2}
{"index": {"_index":"test_19_decay","_id": "3"}}
{"name":"golang","location": {"lon": 73.21,"lat": -22.11},"score": 2.2}
{"index": {"_index":"test_19_decay","_id": "4"}}
{"name":"nodejs","location": {"lon": -98.21,"lat": -44.11},"score": 5.0}
{"index": {"_index":"test_19_decay","_id": "5"}}
{"name":"rust","location": {"lon": 65.12,"lat": 56.23},"score": 1.2}
GET test_19_decay/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "gauss": {
            "location": {
              "origin": "56.23,65.12",
              "scale": "10km",
              "offset": "1km"
            }
          },
          "weight": 2
        },
        {
          "script_score": {
            "script": {
              "source": "_score * doc['score'].value"
            }
          }
        }
      ],
      "score_mode": "sum", 
      "boost_mode": "sum"
    }
  }
}

gauss 函数说明
在坐标 (56.23,65.12) 附近 1km 内,得分始终保持为 1。在 10km 内,得分会保持较高。

5.2 exp

exp 使用指数衰减来计算得分,远离 origin 得分会快速降低,适合对距离或时间敏感的,使用上和 gauss 一致。

GET test_19_decay/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "exp": {
            "location": {
              "origin": "56.23,65.12",
              "scale": "10km",
              "offset": "1km"
            }
          },
          "weight": 2
        },
        {
          "script_score": {
            "script": {
              "source": "_score * doc['score'].value"
            }
          }
        }
      ],
      "score_mode": "sum", 
      "boost_mode": "sum"
    }
  }
}
5.3 linear

linear 衰退函数使用线性方式调整得分。随着距离的增加,得分按线性方式逐渐减少,适合需要平滑衰减的场景,使用上和 gauss 一致。

GET test_19_decay/_search
{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "linear": {
            "location": {
              "origin": "56.23,65.12",
              "scale": "10km",
              "offset": "1km"
            }
          },
          "weight": 2
        },
        {
          "script_score": {
            "script": {
              "source": "_score * doc['score'].value"
            }
          }
        }
      ],
      "score_mode": "sum", 
      "boost_mode": "sum"
    }
  }
}

http://www.kler.cn/news/330644.html

相关文章:

  • 工具笔记之生成图表和可视化的标记语言Mermaid
  • WPF后台创建控件和绑定
  • uniapp中在web端如何友好的展示app当前的版本等信息
  • 知识图谱入门——6:Cypher 查询语言高级组合用法(查询链式操作、复杂路径匹配、条件逻辑、动态模式创建,以及通过事务控制和性能优化处理大规模数据。
  • Python | Leetcode Python题解之第445题两数相加II
  • pdfbox麒麟docker转PDF乱码问题
  • Brave编译指南2024 MacOS篇-环境配置(四)
  • 加密与安全_TOTP 一次性密码生成算法
  • 行为设计模式 -策略设计模式- JAVA
  • sentinel原理源码分析系列(三)-启动和初始化
  • 人生四大“钱关”过不去,我推荐你读这4本书
  • Redis接口访问优化
  • 六.应用层
  • python 实现power iteration幂迭代算法
  • 【C语言指南】数据类型详解(下)——自定义类型
  • 【Android 14源码分析】Activity启动流程-3
  • 全栈杂谈第四期 什么是雪花算法
  • 打造智慧金融:引领未来的投资之路
  • 基于RBAC的通用权限管理系统的详细分析与实现(实现篇-Spring Security安全管理框架)
  • 如何避免我的住宅ip被污染