Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for random_score function:
* can be used to return matching results in random order Closes #1170
- Loading branch information
Showing
8 changed files
with
401 additions
and
4 deletions.
There are no files selected for viewing
99 changes: 99 additions & 0 deletions
99
src/main/java/org/elasticsearch/common/lucene/search/function/RandomScoreFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch licenses this | ||
* file to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.common.lucene.search.function; | ||
|
||
import org.apache.lucene.index.AtomicReaderContext; | ||
import org.apache.lucene.search.Explanation; | ||
|
||
/** | ||
* | ||
*/ | ||
public class RandomScoreFunction implements ScoreFunction { | ||
|
||
private final PRNG prng; | ||
private int docBase; | ||
|
||
public RandomScoreFunction(long seed) { | ||
this.prng = new PRNG(seed); | ||
} | ||
|
||
@Override | ||
public void setNextReader(AtomicReaderContext context) { | ||
this.docBase = context.docBase; | ||
} | ||
|
||
@Override | ||
public double score(int docId, float subQueryScore) { | ||
return prng.random(docBase + docId); | ||
} | ||
|
||
@Override | ||
public double factor(int docId) { | ||
return prng.seed; | ||
} | ||
|
||
@Override | ||
public Explanation explainScore(int docId, Explanation subQueryExpl) { | ||
Explanation exp = new Explanation(); | ||
exp.setDescription("random score function (seed: " + prng.originalSeed + ")"); | ||
exp.addDetail(subQueryExpl); | ||
return exp; | ||
} | ||
|
||
@Override | ||
public Explanation explainFactor(int docId) { | ||
Explanation exp = new Explanation(); | ||
exp.setDescription("seed: " + prng.originalSeed + ")"); | ||
return exp; | ||
} | ||
|
||
/** | ||
* Algorithm based on {@link java.util.Random} except this one is not | ||
* thread safe | ||
*/ | ||
static class PRNG { | ||
|
||
private static final long multiplier = 0x5DEECE66DL; | ||
private static final long addend = 0xBL; | ||
private static final long mask = (1L << 48) - 1; | ||
|
||
final long originalSeed; | ||
long seed; | ||
|
||
PRNG(long seed) { | ||
this.originalSeed = seed; | ||
this.seed = (seed ^ multiplier) & mask; | ||
} | ||
|
||
public float random(int doc) { | ||
if (doc == 0) { | ||
doc = -17; | ||
} | ||
return nextFloat() * (doc ^ 0xCAFEBAB); | ||
} | ||
|
||
public float nextFloat() { | ||
seed = (seed * multiplier + addend) & mask; | ||
int r = (int)(seed >>> 24); | ||
return r / ((float)(1 << 24)); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...n/java/org/elasticsearch/index/query/functionscore/random/RandomScoreFunctionBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch licenses this | ||
* file to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.elasticsearch.index.query.functionscore.random; | ||
|
||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* A function that computes a random score for the matched documents | ||
*/ | ||
public class RandomScoreFunctionBuilder implements ScoreFunctionBuilder { | ||
|
||
private Long seed = null; | ||
|
||
public RandomScoreFunctionBuilder() { | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return RandomScoreFunctionParser.NAMES[0]; | ||
} | ||
|
||
/** | ||
* Sets the seed based on which the random number will be generated. Using the same seed is guaranteed to generate the same | ||
* random number for a specific doc. | ||
* | ||
* @param seed The seed. | ||
*/ | ||
public RandomScoreFunctionBuilder seed(long seed) { | ||
this.seed = seed; | ||
return this; | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(getName()); | ||
if (seed != null) { | ||
builder.field("seed", seed.longValue()); | ||
} | ||
return builder.endObject(); | ||
} | ||
|
||
} |
78 changes: 78 additions & 0 deletions
78
...in/java/org/elasticsearch/index/query/functionscore/random/RandomScoreFunctionParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Licensed to ElasticSearch and Shay Banon under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. ElasticSearch licenses this | ||
* file to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
|
||
|
||
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 java.io.IOException; | ||
import java.util.Map; | ||
|
||
/** | ||
* | ||
*/ | ||
public class RandomScoreFunctionParser implements ScoreFunctionParser { | ||
|
||
public static String[] NAMES = { "random_score", "randomScore" }; | ||
|
||
@Inject | ||
public RandomScoreFunctionParser() { | ||
} | ||
|
||
@Override | ||
public String[] getNames() { | ||
return NAMES; | ||
} | ||
|
||
@Override | ||
public ScoreFunction parse(QueryParseContext parseContext, XContentParser parser) throws IOException, QueryParsingException { | ||
|
||
long seed = -1; | ||
|
||
String currentFieldName = null; | ||
XContentParser.Token token; | ||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { | ||
if (token == XContentParser.Token.FIELD_NAME) { | ||
currentFieldName = parser.currentName(); | ||
} else if (token.isValue()) { | ||
if ("seed".equals(currentFieldName)) { | ||
seed = parser.longValue(); | ||
} else { | ||
throw new QueryParsingException(parseContext.index(), NAMES[0] + " query does not support [" + currentFieldName + "]"); | ||
} | ||
} | ||
} | ||
|
||
if (seed == -1) { | ||
seed = parseContext.nowInMillis(); | ||
} | ||
|
||
return new RandomScoreFunction(seed); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.