random_score function - Added the index name and shard id to the randomization, and improved the PRNG itself

Closes #3559
This commit is contained in:
uboness 2013-08-23 02:46:01 +02:00
parent 109e2944f2
commit 4b3a883111
3 changed files with 30 additions and 10 deletions

View File

@ -64,9 +64,10 @@ public class RandomScoreFunction implements ScoreFunction {
return exp;
}
/**
* Algorithm based on {@link java.util.Random} except this one is not
* thread safe
* Algorithm largely based on {@link java.util.Random} except this one is not
* thread safe and it incorporates the doc id on next();
*/
static class PRNG {
@ -84,15 +85,20 @@ public class RandomScoreFunction implements ScoreFunction {
public float random(int doc) {
if (doc == 0) {
doc = -17;
}
return nextFloat() * (doc ^ 0xCAFEBAB);
doc = 0xCAFEBAB;
}
public float nextFloat() {
long rand = doc;
rand |= rand << 32;
rand ^= rand;
return nextFloat(rand);
}
public float nextFloat(long rand) {
seed = (seed * multiplier + addend) & mask;
int r = (int)(seed >>> 24);
return r / ((float)(1 << 24));
rand ^= seed;
double result = rand / (double)(1L << 54);
return (float) result;
}
}

View File

@ -24,15 +24,14 @@ package org.elasticsearch.index.query.functionscore.random;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.function.RandomScoreFunction;
import org.elasticsearch.common.lucene.search.function.ScoreFunction;
import org.elasticsearch.common.lucene.search.function.ScriptScoreFunction;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryParsingException;
import org.elasticsearch.index.query.functionscore.ScoreFunctionParser;
import org.elasticsearch.script.SearchScript;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
import java.util.Map;
/**
*
@ -73,6 +72,17 @@ public class RandomScoreFunctionParser implements ScoreFunctionParser {
seed = parseContext.nowInMillis();
}
ShardId shardId = SearchContext.current().indexShard().shardId();
seed = salt(seed, shardId.index().name(), shardId.id());
return new RandomScoreFunction(seed);
}
public static long salt(long seed, String index, int shardId) {
long salt = index.hashCode();
salt = salt << 32;
salt |= shardId;
return salt^seed;
}
}

View File

@ -107,15 +107,19 @@ public class RandomScoreFunctionTests extends AbstractSharedClusterTest {
int filled = 0;
int maxRepeat = 0;
int sumRepeat = 0;
for (int i = 0; i < matrix.length; i++) {
int value = matrix[i];
sumRepeat += value;
maxRepeat = Math.max(maxRepeat, value);
if (value > 0) {
filled++;
}
}
System.out.println();
System.out.println("max repeat: " + maxRepeat);
System.out.println("avg repeat: " + sumRepeat / (double)filled);
System.out.println("distribution: " + filled/(double)count);
int percentile50 = filled / 2;