day07 Elasticsearch高级
学习目标
- 能够使用function_score修改文档得分
- 能够说出深度分页的方案
- 能够使用Java Client实现高亮显示
- 能够使用Java Client测试地理坐标查询
- 能够使用Java Client测试聚合查询
- 能够说出实现同义词的方案
- 能够说出自动补全方案
- 能够完善商城项目商品搜索功能
- 能够实现商城项目自动补全功能
1 搜索高级
1.1. 修改文档得分
1.1.1 function_score
当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。
例如,我们搜索 "手机",结果如下:
_score:文档与用户搜索的关键字的相关度得分

在实际业务需求中,常常会有竞价排名的功能。不是相关度越高排名越靠前,而是掏的钱多的排名靠前。
例如在百度中搜索Java培训,排名靠前的就是广告推广:

要想人为控制相关性算分,就需要利用elasticsearch中的function score 查询了。
一个例子:
给小米这个品牌的手机算分提高十倍,分析如下:
- 过滤条件:品牌必须为小米
- 算分函数:常量weight,值为10
- 算分模式:相乘multiply
GET /items/_search
{
"query": {
"function_score": {
"query": {
"match": {
"name":"手机"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "小米"
}
},
"weight": 10
}
],
"boost_mode": "multiply"
}
},
"from": 0,
"size": 10
}从结果可以看到小米手机排在前边,因为对品牌为“小米”的文档得分在原有分值基础上乘以10,分值越大越排在前边。
function score的运行流程如下:
- 1)根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)
- 2)根据过滤条件,过滤文档
- 3)符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)
- 4)将原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分。
因此,其中的关键点是:
- 过滤条件:决定哪些文档的算分被修改
- 算分函数:决定函数算分的算法
- 运算模式:决定最终算分结果
本例中function_score的语法如下:
function score 查询中包含四部分内容:
原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)
过滤条件:filter部分,符合该条件的文档才会重新算分
算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数
- weight:函数结果是常量
- field_value_factor:以文档中的某个字段值作为函数结果,适用于那些需要根据某个数值字段来影响文档排序的情况,例如根据产品的价格、文章的阅读量或者用户的活跃度来对结果进行评分。
- random_score:以随机数作为函数结果,用于测试或某些特定的用例,比如创建一个随机排序的效果
- script_score:自定义算分函数算法,允许你在查询时动态地编写脚本来计算每个文档的分数
boost_mode运算模式:决定了如何将评分函数的结果与基础查询得分相结合,包括:
- multiply:评分函数的结果与基础查询的得分相乘。这是默认行为,适用于希望评分函数增强或减弱基础查询得分的情况。
- replace:评分函数的结果将完全替换基础查询的得分。这意味着最终得分将完全基于评分函数的结果,而不考虑基础查询的原始得分。
sum:评分函数的结果与基础查询的得分相加。这使得评分函数的结果直接增加到基础查询得分上,适合于希望累加评分因素的情况。avg:评分函数的结果与基础查询的得分取平均值。这种方式适用于希望平衡基础查询得分与评分函数得分的情况。
算分函数的其它选项,比如:field_value_factor、script_score大家使用AI自学。
示例2:
将下边的查询改为算分函数查询,品牌为“爱氏晨曦”排在前边
GET /items/_search
{
"from" : 0,
"query" : {
"multi_match" : {
"fields" : [ "name", "category" ],
"query" : "脱脂牛奶"
}
},
"size" : 5
}1.1.2 Java Client
使用Java Client实现算分函数查询
@Test
void testFunctionScoreQuery() throws Exception {
//构建请求
SearchRequest.Builder builder = new SearchRequest.Builder();
//设置索引
builder.index("items");
//设置查询条件
SearchRequest.Builder searchRequestBuilder = builder.query(q -> q
.functionScore(f -> f
.query(q1 -> q1
.match(m -> m
.field("name")
.query("手机"))
)
.functions(fn -> fn
.filter(f1 -> f1
.term(t -> t.field("brand").value("小米")))
.weight(10d)
)
.boostMode(FunctionBoostMode.Multiply))
).from(0).size(10);
SearchRequest build = searchRequestBuilder.build();
//执行请求
SearchResponse<ItemDoc> searchResponse = esClient.search(build, ItemDoc.class);
//解析结果
handleResponse(searchResponse);
}请免费关注 预见猿份 公众号,发送:yjoffer.com,获取解锁密码
微信扫码关注关注公众号回复获取密码后,在下方输入并点击解锁,本机后续再读无需重复输入。
