一 、function score详解

1.1 function score 查询中包含四部分内容:

1)原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)

2)过滤条件:filter部分,符合该条件的文档才会重新算分

3)算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score);

1.2 四种算分函数:

  • weight:函数结果是常量
  • field_value_factor:以文档中的某个字段值作为函数结果
  • random_score:以随机数作为函数结果
  • script_score:自定义算分函数算法
  • 1.3 运算模式

    算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:

  • multiply:相乘
  • replace:用function score替换query score
  • 其它,例如:sum、avg、max、min
  • 注意,搜索时,参与打分的字段越多,查询的性能也越差。因此这种多条件查询时,建议这样做: 
    * 搜索框的关键字搜索,是全文检索查询,使用must查询,参与算分;
    * 其它过滤条件,采用filter查询。不参与算分;
    * must:必须匹配的条件,可以理解为“与”
    * should:选择性匹配的条件,可以理解为“或”
    * must_not:必须不匹配的条件,不参与打分
    * filter:必须匹配的条件,不参与打分**
    

    二、java 实现示例

    Map<String, JsonData> gaussParams = CollectionUtils.newHashMap(8);
    gaussParams.put("origin",JsonData.of(LocalDate.now().toString()));
    gaussParams.put("scale",JsonData.of("7d"));
    gaussParams.put("offset",JsonData.of("0"));
    gaussParams.put("decay",JsonData.of(0.5));
    //高斯衰减函数
    String  decayDateGauss = "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['pubDate'].value)";
    * weight 为每个文档应用一个简单的而不被正则化的权重提升值:当 weight 为 2 时,最终结果为 2 * _score
    * field_value_factor 使用这个值来修改 _score,如将流行度或评分作为考虑因素。
    * random_score 为每个用户都使用一个不同的随机分数来对结果排序,但对某一具体用户来说,看到的顺序始终是一致的。
    * Decay functions — linear, exp, gauss 以某个字段的值为标准,距离某个值越近得分越高。
    * script_score 如果需求超出以上范围时,用自定义脚本完全控制分数计算的逻辑。 
    * 它还有一个属性boost_mode可以指定计算后的分数与原始的_score如何合并,有以下选项:
    *   multiply 将分数与函数值相乘(默认)
    *   sum 将分数与函数值相加
    *   min 分数与函数值的较小值
    *   max 分数与函数值的较大值
    *   replace 函数值替代分数
    nativeQueryBuilder.withQuery(
                    f -> f.functionScore(
                            fs -> fs.query(q -> q.bool(boolBuilder.build()))
                                    .functions( FunctionScore.of(func -> func.filter(
                                                            fq -> fq.match(ft -> ft.field("title").query(keyword)))
                                                    .weight(10.0)
                                            FunctionScore.of(func -> func.filter(
                                                            fq -> fq.match(ft -> ft.field("content").query(keyword)))
                                                    .fieldValueFactor(v ->v.field("id").factor(0.5))
                                            FunctionScore.of(func -> func.filter(
                                                            fq -> fq.match(ft -> ft.field("companies").query(keyword)))
                                                    .randomScore(v -> v.field("companies"))
                                            FunctionScore.of(func -> func.scriptScore(fq -> fq.script(
                                                                    i -> i.inline(il -> il.source(decayDateGauss).params(gaussParams))
                                    .scoreMode(FunctionScoreMode.Sum)
                                    .boostMode(FunctionBoostMode.Sum)
                                    .minScore(1.0)
    

    相应的DSL语句

    至此关于es的搜索功能系列暂时告一段落。