ES 自定义打分(下)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ES 自定义打分

默认情况下,即不设置 field 时会使用 Lucene doc ids 作为随机源去生成随机值,但是这会消耗大量内存,官方建议可以设置 field_seq_no ,主要注意的是,即使指定了相同的 seed ,随机值某些情况下也会改变,这是因为一旦字段进行了更新,_seq_no 也会更新,进而导致随机源发生变化。

多个函数组合示例:

GET /_search
{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "5",
      "functions": [
        {
          "filter": { "match": { "test": "bar" } },
          "random_score": {},
          "weight": 23
        },
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 42
        }
      ],
      "max_boost": 42,
      "score_mode": "max",
      "boost_mode": "multiply",
      "min_score": 42
    }
  }
}

上例 functions 中设置了两个打分函数:

一个是 random_score 随机打分,并且 weight 是 23另一个只有 weight 是 42

假设:

第一个函数随机打分得到了 0.1 ,再与 weight 相乘就是 2.3第二个函数只有 weight ,那么这个函数得到的分数就是 weight 的值 42

score_mode 设置为了 max,意思是取两个打分函数的最大值作为 func_score,对应上述假设也就是 2.3 和 42 两者中的最大值,即 func_score = 42

boost_mode 设置为了 multiply,就是把原来的 query_scorefunc_score 相乘就得到了最终的 score 分数。

参数 score_mode 指定多个打分函数如何组合计算出新的分数:

multiply : 分数相乘(默认)sum : 相加avg : 加权平均值first : 使用第一个 filter 函数的分数max : 取最大值min : 取最小值

为了避免新的分数的数值过高,可以通过 max_boost 参数去设置上限。

需要注意的是:不论我们怎么自定义打分,都不会改变原始 query 的匹配行为,我们自定义打分,都是在原始 query 查询结束后,对每一个匹配的文档进行重新算分。

为了排除掉一些分数太低的结果,我们可以通过 min_score 参数设置最小分数阈值。

field_value_factor

field_value_factor 使用字段的数值参与计算分数。

例如使用 likes 点赞数字段进行综合搜索:

{
  "query": {
    "function_score": {
      "query": { "match": { "message": "elasticsearch" } },
      "field_value_factor": {
        "field": "likes",
        "factor": 1.2,
        "missing": 1,
        "modifier": "log1p"
      }
    }
  }
}

说明:

field : 参与计算的字段。factor : 乘积因子,默认为 1 ,将会与 field 的字段值相乘。missing : 如果 field 字段不存在则使用 missing 指定的缺省值。modifier : 计算函数,为了避免分数相差过大,用于平滑分数,可以是以下之一:none : 不处理,默认log : log(factor * field_value)log1p : log(1 + factor * field_value)log2p : log(2 + factor * field_value)ln : ln(factor * field_value)ln1p : ln(1 + factor * field_value)ln2p : ln(2 + factor * field_value)square : 平方,(factor * field_value)^2sqrt : 开方,sqrt(factor * field_value)reciprocal : 求倒数,1/(factor * field_value)

假设某个匹配的文档的点赞数是 1000 ,那么例子中其打分函数生成的分数就是 log(1 + 1.2 * 1000),最终的分数是原来的 query 分数与此打分函数分数相差的结果。

decay_function

decay_function 衰减函数,例如:

以某个数值作为中心点,距离多少的范围之外逐渐衰减(缩小分数)以某个日期作为中心点,距离多久的范围之外逐渐衰减(缩小分数)以某个地理位置点作为中心点,方圆多少距离之外逐渐衰减(缩小分数)

示例:

"DECAY_FUNCTION": {
    "FIELD_NAME": {
          "origin": "30, 120",
          "scale": "2km",
          "offset": "0km",
          "decay": 0.33
    }
}

上例的意思就是在距中心点方圆 2 公里之外,分数减少到三分之一(乘以 decay 的值 0.33)。

DECAY_FUNCTION 可以是以下任意一种函数:

linear : 线性函数

exp : 指数函数

gauss : 高斯函数

origin : 中心点,只能是数值、日期、geo-point

scale : 定义到中心点的距离

offset : 偏移量,默认 0

decay : 衰减指数,默认是 0.5

示例:

GET /_search
{
  "query": {
    "function_score": {
      "gauss": {
        "@timestamp": {
          "origin": "2013-09-17",
          "scale": "10d",
          "offset": "5d",
          "decay": 0.5
        }
      }
    }
  }
}

中心点是 2013-09-17 日期,scale 是 10d 意味着日期范围是 2013-09-12 到 2013-09-22 的文档分数权重是 1 ,日期在 scale + offset = 15d 之外的文档权重是 0.5 。

如果参与计算的字段有多个值,默认选择最靠近中心点的值,也就是离中心点的最近距离,可以通过 multi_value_mode 设置:

min : 最近距离

max : 最远距离

avg : 平均距离

sum : 所有距离累加

示例:

GET /_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "properties": "大阳台"
        }
      },
      "functions": [
        {
          "gauss": {
            "price": {
              "origin": "0",
              "scale": "2000"
            }
          }
        },
        {
          "gauss": {
            "location": {
              "origin": "30, 120",
              "scale": "2km"
            }
          }
        }
      ],
      "score_mode": "multiply"
    }
  }
}

假设这是搜索大阳台的房源,上例设置了 price 价格字段的中心点是 0 ,范围 2000 以内,以及 location 地理位置字段的中心点是 "30, 120" ,方圆 2km 之内,在这个范围之外的匹配结果的 score 分数会进行高斯衰减,即打分降低。

script_score

script_score 自定义脚本打分,如果上面的打分函数都满足不了你,你还可以直接编写脚本打分。

示例:

GET /_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "message": "elasticsearch" }
      },
      "script_score": {
        "script": {
          "source": "Math.log(2 + doc['my-int'].value)"
        }
      }
    }
  }
}

在脚本中通过 doc['field'] 的形式去引用字段,doc['field'].value 就是使用字段值。

你也可以把额外的参数与脚本内容分开:

GET /_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "message": "elasticsearch" }
      },
      "script_score": {
        "script": {
          "params": {
            "a": 5,
            "b": 1.2
          },
          "source": "params.a / Math.pow(params.b, doc['my-int'].value)"
        }
      }
    }
  }
}

结语

通过了解 Elasticsearch 的自定义打分相信你能更好的完成符合业务的综合性搜索。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
前端开发 API
ES 高级实战(四)查询 ES 数据
ES 高级实战(四)查询 ES 数据
1281 0
ES 高级实战(四)查询 ES 数据
|
11天前
|
机器学习/深度学习 数据挖掘 索引
Elasticsearch 如何把评分限定在0到1之间?
Elasticsearch 如何把评分限定在0到1之间?
22 0
|
11天前
|
供应链 搜索推荐
偏好类标签支持自定义统计方式,标签场景覆盖更广
在个性化营销场景,零售商必须理解顾客的行为才能更准确的预测客户需求,优化库存管理、制定营销策略,并提供个性化的购物体验,然而偏好类标签的加工不仅仅是简单的属性出现频次或最大值的统计,Dataphin V4.0版本新增了自定义统计的方式加工偏好标签,通过简单的配置即可完成复杂的标签加工场景。
|
11天前
|
JSON 前端开发 JavaScript
ES6(2015)-ES13(2022)新增特性大总结
ES6(2015)-ES13(2022)新增特性大总结
52 0
|
5月前
|
JavaScript 前端开发
ES6学习(四)—字符串的新增方法
ES6学习(四)—字符串的新增方法
|
8月前
ES 自定义打分(上)
ES 自定义打分
55 0
|
存储 分布式计算 搜索推荐
ES自定义评分机制:function_score查询详解
ES自定义评分机制:function_score查询详解
1043 0
ES自定义评分机制:function_score查询详解
|
存储 Java API
ES多字段匹配查询时的权重控制
ES多字段匹配查询时的权重控制
659 0
ES多字段匹配查询时的权重控制
|
11月前
|
自然语言处理 JavaScript 前端开发
每天3分钟,重学ES6-ES12(三)标签模版字符串
每天3分钟,重学ES6-ES12(三)标签模版字符串
64 0
ES查询学习(随时更新)
ES查询学习(随时更新)
113 0