Stay hungry, Stay foolish

0%

Elasticsearch Java Api客户端function_score查询问题

Elasticsearch Java API Client 是官方新出的,向前兼容的Java客户端,我们项目在ES升级时最终选择了它

官方推荐使用lambda的方式写,于是我将业务中一个function_score dsl转成代码的形式如下

1
2
3
4
5
6
7
8
FunctionScoreQuery functionScore = FunctionScoreQuery.of(fs -> fs
.functions(
FunctionScore.of(
fn -> fn.filter(f -> f.term(t -> t.field("mdd").boost(1f).value(FieldValue.of("北京")))).weight(2d)),
FunctionScore.of(
fn -> fn.filter(f -> f.matchAll(m -> m.boost(1f))).fieldValueFactor(fvf -> fvf.field("level").modifier(FieldValueFactorModifier.None).factor(1.2d)))
)
);

IntelliJ IDEA 报错了——提示需要转换成 ObjectBuilder

看下源码

发现是触发了 ObjectBuilder 的类型约束

第一个 function 报错是因为 weight 返回的是 FunctionScore.Builder

第二个 function 没有报错是因为fieldValueFactor 返回的是 FunctionScore.Builder.ContainerBuilder

FunctionScore.Builder.ContainerBuilderObjectBuilder 的实现

也就是说只要返回 FunctionScore.Builder.ContainerBuilder 这个类型就行了

有哪些方法是返回这个类型的呢?

  • exp
  • guass
  • linear
  • fieldValueFactor
  • randomScore
  • scriptScore

但是又不能给第一个function强制加上,会影响算分

那么,只想使用filter和weight怎么办呢?

其实官方包里已经安排上了,就在ContainerBuilder 类中

直接实例化一个仅包含 filter 和 wight 的 ContainerBuilder 即可

1
2
3
4
5
6
7
8
FunctionScoreQuery functionScore = FunctionScoreQuery.of(fs -> fs
.functions(
FunctionScore.of(
fn -> (fn.new ContainerBuilder()).filter(f -> f.term(t -> t.field("mdd").boost(1f).value(FieldValue.of("北京")))).weight(2d)),
FunctionScore.of(
fn -> fn.filter(f -> f.matchAll(m -> m.boost(1f))).fieldValueFactor(fvf -> fvf.field("level").modifier(FieldValueFactorModifier.None).factor(1.2d)))
)
);
据说打赏我的人,代码没有BUG