11package com .bigdataboutique .elasticsearch .plugin ;
22
3+ import com .bigdataboutique .elasticsearch .plugin .exceptions .ScoreFunctionParseException ;
34import com .bigdataboutique .elasticsearch .plugin .exceptions .ScoreOperatorException ;// Exceptions
45
56import org .apache .logging .log4j .LogManager ;
@@ -49,6 +50,8 @@ public class RedisRescoreBuilder extends RescorerBuilder<RedisRescoreBuilder> {
4950 private static final String SCORE_OPERATOR_DEFAULT = "ADD" ;
5051 private static final String BOOST_OPERATOR_DEFAULT = "ADD" ;
5152 private static final float BOOST_WEIGHT_DEFAULT = 1f ;
53+
54+
5255 //------------------------------------------------------------------------------------------------------
5356
5457 protected static final Logger log = LogManager .getLogger (RedisRescoreBuilder .class );
@@ -60,6 +63,7 @@ public class RedisRescoreBuilder extends RescorerBuilder<RedisRescoreBuilder> {
6063 private final String boostOperator ;
6164 private final Float boostWeight ;
6265 private final Float [] scoreWeights ;
66+ private final String [] scoreFunctions ;
6367
6468
6569
@@ -106,7 +110,8 @@ public static Float[] GetFloatArray(@Nullable ArrayList<?> arr) { // Transforms
106110// Constructors--------------------------------------------------------------------------------------------------
107111 public RedisRescoreBuilder (final String keyField , @ Nullable String keyPrefix , @ Nullable String scoreOperator ,
108112 @ Nullable String [] keyPrefixes , @ Nullable String boostOperator ,
109- @ Nullable Float boostWeight , @ Nullable Float [] scoreWeights )
113+ @ Nullable Float boostWeight , @ Nullable Float [] scoreWeights ,
114+ @ Nullable String [] scoreFunctions )
110115 throws ScoreOperatorException {
111116
112117 this .keyField = keyField ;
@@ -116,6 +121,7 @@ public RedisRescoreBuilder(final String keyField, @Nullable String keyPrefix, @N
116121 this .keyPrefixes = keyPrefixes ;
117122 this .boostWeight = boostWeight == null ? BOOST_WEIGHT_DEFAULT : boostWeight ;
118123 this .scoreWeights = scoreWeights ;
124+ this .scoreFunctions = scoreFunctions ;
119125
120126
121127 if (!checkOperator (this .scoreOperator ))
@@ -136,6 +142,8 @@ public RedisRescoreBuilder(StreamInput in) throws IOException {
136142 boostOperator = BOOST_OPERATOR_DEFAULT ;
137143 boostWeight = BOOST_WEIGHT_DEFAULT ;
138144 scoreWeights = null ;
145+ scoreFunctions = null ;
146+
139147
140148 }
141149//--------------------------------------------------------------------------------------------------
@@ -163,6 +171,8 @@ public RescorerBuilder<RedisRescoreBuilder> rewrite(QueryRewriteContext ctx) thr
163171 private static final ParseField BOOST_OPERATOR = new ParseField ("boost_operator" );
164172 private static final ParseField BOOST_WEIGHT = new ParseField ("boost_weight" );
165173 private static final ParseField SCORE_WEIGHTS = new ParseField ("score_weights" );
174+ private static final ParseField SCORE_FUNCTIONS = new ParseField ("score_functions" );
175+
166176
167177 @ Override
168178 protected void doXContent (XContentBuilder builder , Params params ) throws IOException {
@@ -180,15 +190,20 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep
180190
181191 builder .field (SCORE_WEIGHTS .getPreferredName (), scoreWeights );
182192
193+ builder .field (SCORE_FUNCTIONS .getPreferredName (), scoreFunctions );
194+
195+
196+
183197 }
184198
199+
185200 private static final ConstructingObjectParser <RedisRescoreBuilder , Void > PARSER =
186201 new ConstructingObjectParser <RedisRescoreBuilder , Void >(NAME ,
187202 args -> {
188203 try {
189204 return new RedisRescoreBuilder ((String ) args [0 ], (String ) args [1 ], (String ) args [2 ],
190205 GetStringArray ((ArrayList <?>) args [3 ]) , (String ) args [4 ],
191- (Float ) args [5 ], GetFloatArray ((ArrayList <?>) args [6 ]));
206+ (Float ) args [5 ], GetFloatArray ((ArrayList <?>) args [6 ]), GetStringArray (( ArrayList <?>) args [ 7 ]) );
192207
193208 } catch (IOException e ) {
194209 throw new IllegalArgumentException (e );
@@ -203,6 +218,7 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep
203218 PARSER .declareString (optionalConstructorArg (), BOOST_OPERATOR );
204219 PARSER .declareFloat (optionalConstructorArg (), BOOST_WEIGHT );
205220 PARSER .declareFloatArray (optionalConstructorArg (), SCORE_WEIGHTS );
221+ PARSER .declareStringArray (optionalConstructorArg (),SCORE_FUNCTIONS );
206222 }
207223 public static RedisRescoreBuilder fromXContent (XContentParser parser ) {
208224 return PARSER .apply (parser , null );
@@ -213,7 +229,7 @@ public RescoreContext innerBuildContext(int windowSize, QueryShardContext contex
213229 IndexFieldData <?> keyField =
214230 this .keyField == null ? null : context .getForField (context .fieldMapper (this .keyField ));
215231 return new RedisRescoreContext (windowSize , keyPrefix , keyField , scoreOperator ,
216- keyPrefixes , boostOperator , boostWeight , scoreWeights );
232+ keyPrefixes , boostOperator , boostWeight , scoreWeights , scoreFunctions );
217233 }
218234
219235 @ Override
@@ -267,18 +283,25 @@ Float[] scoreWeights(){
267283 return scoreWeights ;
268284 }
269285
286+ @ Nullable
287+ String [] scoreFunctions (){
288+ return scoreFunctions ;
289+ }
290+
291+
270292 private static class RedisRescoreContext extends RescoreContext {
271293 private final String keyPrefix ;
272294 private final String [] keyPrefixes ;
273295 private final String scoreOperator ;
274296 private final String boostOperator ;
275297 private final Float boostWeight ;
276298 private final Float [] scoreWeights ;
299+ private final String [] scoreFunctions ;
277300 @ Nullable
278301 private final IndexFieldData <?> keyField ;
279302
280303 RedisRescoreContext (int windowSize , String keyPrefix , @ Nullable IndexFieldData <?> keyField , String scoreOperator ,
281- String [] keyPrefixes , String boostOperator , Float boostWeight , Float [] scoreWeights ) {
304+ String [] keyPrefixes , String boostOperator , Float boostWeight , Float [] scoreWeights , String [] scoreFunctions ) {
282305 super (windowSize , RedisRescorer .INSTANCE );
283306 this .keyPrefix = keyPrefix ;
284307 this .keyField = keyField ;
@@ -287,6 +310,7 @@ private static class RedisRescoreContext extends RescoreContext {
287310 this .boostOperator = boostOperator ;
288311 this .boostWeight = boostWeight ;
289312 this .scoreWeights = scoreWeights ;
313+ this .scoreFunctions = scoreFunctions ;
290314
291315 }
292316 }
@@ -382,21 +406,25 @@ public TopDocs rescore(TopDocs topDocs, IndexSearcher searcher, RescoreContext r
382406 float scoreWeight = getScoreWeight (context .scoreWeights , j );
383407
384408 if (redisScore == 0 )
385- redisScore = getScoreFactor (term , prefix , scoreWeight );
409+ redisScore = getRescore (term , prefix , scoreWeight , j , context . scoreFunctions );
386410
387411 else {
388412 switch (context .scoreOperator ) {
389413 case "ADD" :
390- redisScore += getScoreFactor (term , prefix , scoreWeight );
414+ redisScore += getRescore (term , prefix , scoreWeight ,
415+ j , context .scoreFunctions );
391416 break ;
392417 case "MULTIPLY" :
393- redisScore *= getScoreFactor (term , prefix , scoreWeight );
418+ redisScore *= getRescore (term , prefix , scoreWeight ,
419+ j , context .scoreFunctions );
394420 break ;
395421 case "SUBTRACT" :
396- redisScore -= getScoreFactor (term , prefix , scoreWeight );
422+ redisScore -= getRescore (term , prefix , scoreWeight ,
423+ j , context .scoreFunctions );
397424 break ;
398425 case "SET" :
399- redisScore = getScoreFactor (term , prefix , scoreWeight );
426+ redisScore = getRescore (term , prefix , scoreWeight ,
427+ j , context .scoreFunctions );
400428 break ;
401429 }
402430 }
@@ -426,25 +454,25 @@ else if (numericDocValues != null) {
426454 float scoreWeight = getScoreWeight (context .scoreWeights , j );
427455
428456 if (redisScore == 0 )
429- redisScore = getScoreFactor (String .valueOf (numericDocValues .nextValue ()),
430- prefix , scoreWeight );
457+ redisScore = getRescore (String .valueOf (numericDocValues .nextValue ()),
458+ prefix , scoreWeight , j , context . scoreFunctions );
431459 else {
432460 switch (context .scoreOperator ) {
433461 case "ADD" :
434- redisScore += getScoreFactor (String .valueOf (numericDocValues .nextValue ()),
435- prefix , scoreWeight );
462+ redisScore += getRescore (String .valueOf (numericDocValues .nextValue ()),
463+ prefix , scoreWeight , j , context . scoreFunctions );
436464 break ;
437465 case "MULTIPLY" :
438- redisScore *= getScoreFactor (String .valueOf (numericDocValues .nextValue ()),
439- prefix , scoreWeight );
466+ redisScore *= getRescore (String .valueOf (numericDocValues .nextValue ()),
467+ prefix , scoreWeight , j , context . scoreFunctions );
440468 break ;
441469 case "SUBTRACT" :
442- redisScore -= getScoreFactor (String .valueOf (numericDocValues .nextValue ()),
443- prefix , scoreWeight );
470+ redisScore -= getRescore (String .valueOf (numericDocValues .nextValue ()),
471+ prefix , scoreWeight , j , context . scoreFunctions );
444472 break ;
445473 case "SET" :
446- redisScore = getScoreFactor (String .valueOf (numericDocValues .nextValue ()),
447- prefix , scoreWeight );
474+ redisScore = getRescore (String .valueOf (numericDocValues .nextValue ()),
475+ prefix , scoreWeight , j , context . scoreFunctions );
448476 break ;
449477 }
450478 }
@@ -490,6 +518,41 @@ else if (numericDocValues != null) {
490518 });
491519 return topDocs ;
492520 }
521+
522+ private static float getRescore (final String key , @ Nullable final String keyPrefix , @ Nullable float scoreWeight ,
523+ @ Nullable int keyPrefixesIndex , @ Nullable String [] scoreFunctions )
524+ throws ScoreFunctionParseException {
525+
526+ if (scoreFunctions == null || scoreFunctions .length == 0 )
527+ return getScoreFactor (key , keyPrefix , scoreWeight );
528+ //add exception here
529+ float scoreFactor = getScoreFactor (key , keyPrefix ,1 );
530+ Float res = null ;
531+
532+ if ( keyPrefixesIndex >= scoreFunctions .length || Objects .equals (scoreFunctions [keyPrefixesIndex ], "null" )){
533+ return scoreFactor * scoreWeight ;
534+ }
535+
536+ try {
537+ String [] parsed = ScoreFunctionParser .getScoreFunctionParser ().parse (scoreFunctions [keyPrefixesIndex ],
538+ String .valueOf (scoreFactor ));
539+
540+
541+ //--------------------------------------------Functions---------------------------------------------------
542+ switch (parsed [0 ]) {
543+ case "pow" :
544+ res = ScoreFunctionsObj .get ().pow (Float .parseFloat (parsed [1 ]), Float .parseFloat (parsed [2 ]));
545+ break ;
546+ }
547+ //--------------------------------------------------------------------------------------------------------
548+ } catch (Exception e ){
549+ throw new ScoreFunctionParseException (scoreFunctions [keyPrefixesIndex ]);
550+ }
551+
552+ return res == null ? scoreFactor * scoreWeight : res * scoreWeight ;
553+ }
554+
555+
493556 //ScoreWeight Default Value must be 1
494557 private static float getScoreFactor (final String key , @ Nullable final String keyPrefix ,float scoreWeight ) {
495558 assert key != null ;
@@ -502,8 +565,9 @@ private static float getScoreFactor(final String key, @Nullable final String key
502565 return 1.0f ;
503566 }
504567
505- try {
568+ try { // Here
506569 return Float .parseFloat (factor ) * scoreWeight ;
570+
507571 } catch (NumberFormatException ignored_e ) {
508572 log .warn ("Redis rescore factor NumberFormatException for key " + fullKey );
509573 return 1.0f ;
0 commit comments