|
@@ -21,22 +21,20 @@ package org.elasticsearch.script;
|
|
|
|
|
|
import org.apache.lucene.util.BytesRef;
|
|
|
import org.apache.lucene.util.StringHelper;
|
|
|
-import org.elasticsearch.common.Randomness;
|
|
|
+import org.elasticsearch.ExceptionsHelper;
|
|
|
import org.elasticsearch.common.geo.GeoDistance;
|
|
|
import org.elasticsearch.common.geo.GeoPoint;
|
|
|
import org.elasticsearch.common.geo.GeoUtils;
|
|
|
import org.elasticsearch.common.time.DateMathParser;
|
|
|
import org.elasticsearch.common.unit.DistanceUnit;
|
|
|
import org.elasticsearch.common.unit.TimeValue;
|
|
|
+import org.elasticsearch.index.fielddata.ScriptDocValues;
|
|
|
import org.elasticsearch.index.mapper.DateFieldMapper;
|
|
|
|
|
|
import java.time.ZoneId;
|
|
|
-import java.util.Random;
|
|
|
|
|
|
-/**
|
|
|
- * ScoringScriptImpl can be used as {@link ScoreScript}
|
|
|
- * to run a previously compiled Painless script.
|
|
|
- */
|
|
|
+import static com.carrotsearch.hppc.BitMixer.mix32;
|
|
|
+
|
|
|
public final class ScoreScriptUtils {
|
|
|
|
|
|
/****** STATIC FUNCTIONS that can be used by users for score calculations **/
|
|
@@ -53,26 +51,50 @@ public final class ScoreScriptUtils {
|
|
|
return Math.pow(value,a) / (Math.pow(k,a) + Math.pow(value,a));
|
|
|
}
|
|
|
|
|
|
+ // random score based on the documents' values of the given field
|
|
|
+ public static final class RandomScoreField {
|
|
|
+ private final ScoreScript scoreScript;
|
|
|
+ private final ScriptDocValues docValues;
|
|
|
+ private final int saltedSeed;
|
|
|
|
|
|
- // reproducible random
|
|
|
- public static double randomReproducible(String seedValue, int seed) {
|
|
|
- int hash = StringHelper.murmurhash3_x86_32(new BytesRef(seedValue), seed);
|
|
|
- return (hash & 0x00FFFFFF) / (float)(1 << 24); // only use the lower 24 bits to construct a float from 0.0-1.0
|
|
|
- }
|
|
|
|
|
|
- // not reproducible random
|
|
|
- public static final class RandomNotReproducible {
|
|
|
- private final Random rnd;
|
|
|
+ public RandomScoreField(ScoreScript scoreScript, int seed, String fieldName) {
|
|
|
+ this.scoreScript = scoreScript;
|
|
|
+ this.docValues = scoreScript.getDoc().get(fieldName);
|
|
|
+ int salt = (scoreScript._getIndex().hashCode() << 10) | scoreScript._getShardId();
|
|
|
+ this.saltedSeed = mix32(salt ^ seed);
|
|
|
|
|
|
- public RandomNotReproducible() {
|
|
|
- this.rnd = Randomness.get();
|
|
|
}
|
|
|
|
|
|
- public double randomNotReproducible() {
|
|
|
- return rnd.nextDouble();
|
|
|
+ public double randomScore() {
|
|
|
+ try {
|
|
|
+ docValues.setNextDocId(scoreScript._getDocId());
|
|
|
+ String seedValue = String.valueOf(docValues.get(0));
|
|
|
+ int hash = StringHelper.murmurhash3_x86_32(new BytesRef(seedValue), saltedSeed);
|
|
|
+ return (hash & 0x00FFFFFF) / (float)(1 << 24); // only use the lower 24 bits to construct a float from 0.0-1.0
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw ExceptionsHelper.convertToElastic(e);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // random score based on the internal Lucene document Ids
|
|
|
+ public static final class RandomScoreDoc {
|
|
|
+ private final ScoreScript scoreScript;
|
|
|
+ private final int saltedSeed;
|
|
|
+
|
|
|
+ public RandomScoreDoc(ScoreScript scoreScript, int seed) {
|
|
|
+ this.scoreScript = scoreScript;
|
|
|
+ int salt = (scoreScript._getIndex().hashCode() << 10) | scoreScript._getShardId();
|
|
|
+ this.saltedSeed = mix32(salt ^ seed);
|
|
|
+ }
|
|
|
+
|
|
|
+ public double randomScore() {
|
|
|
+ String seedValue = Integer.toString(scoreScript._getDocBaseId());
|
|
|
+ int hash = StringHelper.murmurhash3_x86_32(new BytesRef(seedValue), saltedSeed);
|
|
|
+ return (hash & 0x00FFFFFF) / (float)(1 << 24); // only use the lower 24 bits to construct a float from 0.0-1.0
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// **** Decay functions on geo field
|
|
|
public static final class DecayGeoLinear {
|