通过案例实战详解elasticsearch自定义打分function_score的使用

这篇具有很好参考价值的文章主要介绍了通过案例实战详解elasticsearch自定义打分function_score的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

elasticsearch给我们提供了很强大的搜索功能,但是有时候仅仅只用相关度打分是不够的,所以elasticsearch给我们提供了自定义打分函数function_score,本文结合简单案例详解function_score的使用方法,关于function-score-query的文档最权威的莫过于官方文档:
function_score官方文档

基本数据准备

我们创建一张新闻表,包含如下字段:

字段 类型 说明
id Long 新闻ID
title string 标题
tags string 标签
read_count long 阅读数
like_count long 点赞数
comment_count long 评论数
rank double 自定义权重
location arrays 文章发布经纬度
pub_time date 发布时间

创建elasticsearchMapping

PUT /news
{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "title": {
        "type": "text",
        "analyzer": "standard"
      },
      "tags": {
        "type": "keyword"
      },
      "read_count": {
        "type": "long"
      },
     "like_count": {
        "type": "long"
      },
     "comment_count": {
        "type": "long"
      },
      "rank": {
        "type": "double"
      },
      "location": {
          "type": "geo_point"
        },
      "pub_time": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

准备测试数据:

id title tags read_count comment_count like_count rank location pub_time
1 台风“杜苏芮”登陆福建晋江 多部门多地全力应对 台风;杜苏芮;福建 10000 2000 600 0 118.55199,24.78144 2023-07-29 09:47
2 受台风“杜苏芮”影响 北京7月29日至8月1日将有强降雨 台风;杜苏芮;北京 1000 200 60 0 116.23128,40.22077 2023-06-29 14:49:38
3 杭州解除台风蓝色预警信号 台风;杭州 10 2 6 0.9 120.21201,30.2084 2020-07-29 14:49:38

批量添加数据到elasticsearch中:

POST _bulk
{"create": {"_index": "news", "_id": 1}}
{"comment_count":600,"id":1,"like_count":2000,"location":[118.55199,24.78144],"pub_time":"2023-07-29 09:47","rank":0.0,"read_count":10000,"tags":["台风","杜苏芮","福建"],"title":"台风“杜苏芮”登陆福建晋江 多部门多地全力应对"}
{"create": {"_index": "news", "_id": 2}}
{"comment_count":60,"id":2,"like_count":200,"location":[116.23128,40.22077],"pub_time":"2023-06-29 14:49:38","rank":0.0,"read_count":1000,"tags":["台风","杜苏芮","北京"],"title":"受台风“杜苏芮”影响 北京7月29日至8月1日将有强降雨"}
{"create": {"_index": "news", "_id": 3}}
{"comment_count":6,"id":3,"like_count":20,"location":[120.21201,30.208],"pub_time":"2020-07-29 14:49:38","rank":0.99,"read_count":100,"tags":["台风","杭州"],"title":"杭州解除台风蓝色预警信号"}

random_score的使用

我们通过random_score理解一下weightscore_mode,boost_mode的作用分别是什么,先直接看Demo


GET /news/_search
{
  "query": {
    "function_score": {
      "query": {"match": {
        "title": "台风"
      }},
      "functions": [
        {
          "random_score": {}, 
          "weight": 1
        },
         {
          "filter": { "match": { "title": "杭州" } },
          "weight":42
        }
      ],
      "score_mode": "sum",
      "boost_mode": "replace"
    }
  }
}

对应JAVA查询代码:

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.matchQuery("title","杭州"));
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[1];
        ScoreFunctionBuilder<RandomScoreFunctionBuilder> randomScoreFilter = new RandomScoreFunctionBuilder();
        ((RandomScoreFunctionBuilder) randomScoreFilter).seed(2);
        filterFunctionBuilders[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(randomScoreFilter);
        FunctionScoreQueryBuilder query = QueryBuilders.functionScoreQuery(queryBuilder, filterFunctionBuilders).scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
        SearchSourceBuilder searchSourceBuilder= new SearchSourceBuilder().query(query);
        SearchRequest searchRequest= new SearchRequest().searchType(SearchType.DFS_QUERY_THEN_FETCH).indices("news").source(searchSourceBuilder);
        SearchResponse response =  restClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        String searchSource;
        for (SearchHit hit : hits)
        {
            searchSource = hit.getSourceAsString();
            System.out.println(searchSource);
        }

查询结果:
通过案例实战详解elasticsearch自定义打分function_score的使用,搜索引擎,elasticsearch,搜索引擎,java

这个查询使用的function_scorequery中通过title搜索“台风”,在functions我们增加了两个打分,一个是random_score,随机生成一个得分,得分的weight权重是1,第二个是如果标题中有“杭州”,得分权重为42,

  • random_score
    顾名思义就是生成一个(0,1)之间的随机得分,我能想到的一个应用场景是,有一天产品要求:每个人看到新闻都不一样,要做到“千人千面”,而且只给你一天的时间,这样我们就可以使用random_score,每次拉取的数据都是随机的,每个人看到的新闻都是不一样的,这个随机查询比Mysql实现简单多了,0成本实现了“千人千面”。

  • weight
    这个就是给生成的得分增加一个权重,在上面的Demo中,我们第一个 weight=1,第二个weight=42,从搜索结果得分可以看出“杭州解除台风蓝色预警信号”这条得分是42.40192,而下面的只有0.8194501,因为增加了42倍的权重。

  • score_mode

score_mode的作用是对functions中计算出来的多个得分做汇总计算,比如我用了是sum,就是指将上面random_score得到的打分和filter中得到的42分相加,也就是说第一条42.40192得分是random_score生成了0.40192再加上filter中得到了42分。score_mode默认是采用multiply,总共有6种计算方式:

random_score函数 计算方式
multiply scores are multiplied (default)
sum scores are summed
avg scores are averaged
first the first function that has a matching filter is applied
max maximum score is used
min minimum score is used
  • boost_mode

boost_mode作用是将functions得到的总分数和我们query查询的得到的分数做计算,比如我们使用的是replace就是完全使用functions中的得分替代query中的得分,boost_mode总共有6种计算方式:

boost_mode函数 得分计算方式
multiply query score and function score is multiplied (default)
replace only function score is used, the query score is ignored
sum query score and function score are added
avg average
max max of query score and function score
min min of query score and function score

script_score的使用

script_score就是用记可以通过各种函数计算你文档中出现的字段,算出一个自己想要的得分,我们直接看Demo

通过案例实战详解elasticsearch自定义打分function_score的使用,搜索引擎,elasticsearch,搜索引擎,java

GET /news/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "title": "台风" }
      },
      "script_score": {
        "script": {
          "params": {
            "readCount": 1,
            "likeCount":5,
            "commentCount":10
          },
          "source": "Math.log(params.readCount* doc['read_count'].value +params.likeCount* doc['like_count'].value+params.commentCount* doc['comment_count'].value) "
        }
      },
      "boost_mode": "multiply"
    }
  }
}

每篇新闻有阅读数点赞数据评论数,我们可以通过这三个指标算出一个分值来评价一篇文章的热度,然后将这个热度和query中的得分相乘,这样热度很高的文章可以排到更前面。在这个Demo中我使用了一个简单的加权来计算文章热度,一般来说阅读数是最大的,点赞数次之,评论数是最小的。

文章热度 = L o g ( 评论数 × 10 + 点赞数 × 5 + 阅读数 ) 文章热度=Log(评论数\times 10+点赞数\times5+阅读数) 文章热度=Log(评论数×10+点赞数×5+阅读数)

这里为了演示,简单算一下文章热度,真实的要比这个复杂的多,可能不同种类的文章重要性也是不一样的。

field_value_factor的使用

field_value_factor可以理解成elasticsearch给你一些内置的script_score,每次写script_score必定不是太方便,如果有一些内置的函数,开箱即用就方便多了,我们直接看Demo

GET /news/_search
{
    "query": {
        "function_score": {
            "query": {
                "match": {
                    "title": "台风"
                }
            },
            "field_value_factor": {
                "field": "rank",
                "factor": 10,
                "modifier": "sqrt",
                "missing": 1
            },
            "boost_mode": "multiply"
        }
    }
}

这里的field_value_factor就对相当script_scoresqrt(10 * doc['rank'].value),这里的factor是乘以多少倍,默认是1倍,missing是如果没有这个字段默认值为1,modifier是计算函数,field是要计算的字段。

modifier计算函数有以下类型可以选择

modifier函数 得分计算方式
none Do not apply any multiplier to the field value
log Take the common logarithm of the field value. Because this function will return a negative value and cause an error if used on values between 0 and 1, it is recommended to use log1p instead.
log1p Add 1 to the field value and take the common logarithm
log2p Add 2 to the field value and take the common logarithm
ln Take the natural logarithm of the field value. Because this function will return a negative value and cause an error if used on values between 0 and 1, it is recommended to use ln1p instead.
ln1p Add 1 to the field value and take the natural logarithm
ln2p Add 2 to the field value and take the natural logarithm
square Square the field value (multiply it by itself)
sqrt Take the square root of the field value
reciprocal Reciprocate the field value, same as 1/x where x is the field’s value

衰减函数Decay functions的使用

衰减函数可以理解成计算文档中某一个字段与给定值的距离,如果距离越近得分就越高,距离越远得分就越低,这个就比较适用于新闻发布时间的衰减了,越久前发布的新闻,得分应该越小,排序越往后。我们直接看Demo

GET /news/_search
{
    "query": {
        "function_score": {
            "query": {
                "match": {
                    "title": "台风"
                }
            },
            "functions": [
                {
                    "gauss": {
                        "pub_time": {
                            "origin": "now",
                            "offset": "7d",
                            "scale": "60d",
                            "decay": 0.9
                        }
                    }
                },
                {
                    "exp": {
                        "location": {
                            "origin": {
                                "lat": 120.21551,
                                "lon": 30.25308
                            },
                            "offset": "50km",
                            "scale": "50km",
                            "decay": 0.1
                        }
                    }
                }
            ],
            "score_mode": "sum", 
            "boost_mode": "sum"
        }
    }
}

搜索结果:
通过案例实战详解elasticsearch自定义打分function_score的使用,搜索引擎,elasticsearch,搜索引擎,java

衰减函数有3种,分别为gauss高斯函数、lin线程函数、exp对数函数,具体的计算公式可以参考官方文档,这里我们主要理解衰减函数的4个参数作用是什么。

通过案例实战详解elasticsearch自定义打分function_score的使用,搜索引擎,elasticsearch,搜索引擎,java

  • origin
    可以理解成计算距离的原点,比如上面计算新闻发布时间的原点是当前时间,计算经纬度的原点是用户搜索位置,比如我在杭州,那么origin就是杭州的经纬度

  • offset
    这个偏移量可以理解成不需要衰减的距离,比如在上面的Demo中,距离pub_timeoffset为7d,意思是说近7天内发布的新闻都不需要衰减,得分直接为1。计算经纬度中的offset为50km意思是说距离用户50km里的新闻不需要衰减,50km内的基本都是杭州本地的新闻,就没必要衰减了。

  • scaledecay
    这两个参数可以参考官方给的三种函数衰减图,scaledecay表示距离为scale后得分衰减到原来的scale倍。比如上面时间衰减offset=7d, scale=60d,decay= 0.9加起来的意思就是7天内的新闻不衰减,67天(7d+60d)前的新闻得分为0.9,在经纬度衰减中offset=50km, scale=50km,decay= 0.1的意思是50km内的距离不衰减,100km(50km+50km)外的数据得分为0.1。

总结

elasticsearchfunction_score给我提供了好几种很灵活的自定义打分策略,在实际项目中需要根据自己的需求合理的组合这些打分策略并调整对应参数才能满足自己的搜索需求,本文主要介绍function_score的使用,接下来我会根据一个实际的搜索应用介绍一下如何组合、设置这些函数以达到比较理解的搜索效果。文章来源地址https://www.toymoban.com/news/detail-617951.html

到了这里,关于通过案例实战详解elasticsearch自定义打分function_score的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ElasticSearch之score打分机制原理

    Elasticsearch 的得分机制是一个基于词频和逆文档词频的公式,简称为 TF-IDF 公式,所以先来研究下 TF-IDF 原理。 TF-IDF 的英文全称是: Term Frequency - Inverse Document Frequency ,中文名称词频-逆文档频率。 常用于文本挖掘,资讯检索等应用,在 NLP 以及推荐等领域都是一个常用的指标

    2023年04月25日
    浏览(79)
  • Elasticsearch:崭新的打分机制 - Learning To Rank (LTR)

    警告 :“学习排名 (Learning To Rank)” 功能处于技术预览版,可能会在未来版本中更改或删除。 Elastic 将努力解决任何问题,但此功能不受官方 GA 功能的支持 SLA 的约束。 注意 :此功能是在版本 8.12.0 中引入的,并且仅适用于某些订阅级别。 有关更多信息,请参阅 https://www.

    2024年04月25日
    浏览(31)
  • SpringBoot 实现 elasticsearch 查询操作(RestHighLevelClient 的案例实战)

    上一节讲述了 SpringBoot 实现 elasticsearch 索引操作,这一章节讲述 SpringBoot 实现 elasticsearch 查询操作。 案例用到的索引库结构

    2024年02月11日
    浏览(45)
  • MapReduce实战小案例(自定义排序、二次排序、分组、分区)

    MapReduce是什么? 我们来看官方文档的解释(我们下载的hadoop中有离线文档:hadoop-2.10.1/share/doc) Hadoop MapReduce 是一个易于编写应用程序的软件框架,它以可靠、容错的方式并行处理商业硬件的大型集群(数千个节点)上的大量数据(数 TB 数据集)。 这里我们可以提炼一下MapReduce的

    2024年02月07日
    浏览(43)
  • 【Python详解】Python类的详细定义与使用案例

    大家好,我是洲洲,欢迎关注,一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢迎大家在CSDN后台私信我! 在Python中,类是一种具有相同属性和方法的对象的抽象。在创建类的实例之

    2024年02月14日
    浏览(39)
  • dsdgen命令 的用法,定义,命令参数详解,以及使用案例

    当下随着数据量不断增长,数据仓库的性能和扩展性成为了关键的课题。为了解决这一问题,需要对数据仓库进行性能测试。TPC-DS(Test Performance Council Decision Support)是一款用于数据仓库基准测试的测试套件,包含了针对数据仓库的45种负载。dsdgen命令是TPC-DS数据生成器的一部分

    2024年02月09日
    浏览(38)
  • Elasticsearch8.8.0 SpringBoot实战操作各种案例(索引操作、聚合、复杂查询、嵌套等)

    Elasticsearch8.8.0 全网最新版教程 从入门到精通 通俗易懂 引入依赖 添加配置文件 application.yaml 导入ca证书到项目中 从任意一个es容器中,拷贝证书到resources目录下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EXytUrDp-1691330960034)(media/16912196423122/16

    2024年02月13日
    浏览(59)
  • 【Spring AOP + 自定义注解 + 动态数据源 实现主从库切换&读写分离】—— 案例实战

                                                 💧 S p r i n g A O P + 主从数据源切换 + 读写分离 + 自定义注解案例实战! color{#FF1493}{Spring AOP + 主从数据源切换 + 读写分离 + 自定义注解 案例实战!} Sp r in g A OP + 主从数据源切换 + 读写分离 + 自定义注解案例

    2024年02月15日
    浏览(39)
  • elasticsearch(ES)分布式搜索引擎03——(RestClient查询文档,ES旅游案例实战)

    文档的查询同样适用昨天学习的 RestHighLevelClient对象,基本步骤包括: 1)准备Request对象 2)准备请求参数 3)发起请求 4)解析响应 我们以match_all查询为例 3.1.1.发起查询请求 代码解读: 第一步,创建 SearchRequest 对象,指定索引库名 第二步,利用 request.source() 构建DSL,DSL中可

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包