use of org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery in project elasticsearch by elastic.
the class CustomUnifiedHighlighter method rewriteCustomQuery.
/**
* Translate custom queries in queries that are supported by the unified highlighter.
*/
private Collection<Query> rewriteCustomQuery(Query query) {
if (query instanceof MultiPhrasePrefixQuery) {
MultiPhrasePrefixQuery mpq = (MultiPhrasePrefixQuery) query;
Term[][] terms = mpq.getTerms();
int[] positions = mpq.getPositions();
SpanQuery[] positionSpanQueries = new SpanQuery[positions.length];
int sizeMinus1 = terms.length - 1;
for (int i = 0; i < positions.length; i++) {
SpanQuery[] innerQueries = new SpanQuery[terms[i].length];
for (int j = 0; j < terms[i].length; j++) {
if (i == sizeMinus1) {
innerQueries[j] = new SpanMultiTermQueryWrapper(new PrefixQuery(terms[i][j]));
} else {
innerQueries[j] = new SpanTermQuery(terms[i][j]);
}
}
if (innerQueries.length > 1) {
positionSpanQueries[i] = new SpanOrQuery(innerQueries);
} else {
positionSpanQueries[i] = innerQueries[0];
}
}
// sum position increments beyond 1
int positionGaps = 0;
if (positions.length >= 2) {
// positions are in increasing order. max(0,...) is just a safeguard.
positionGaps = Math.max(0, positions[positions.length - 1] - positions[0] - positions.length + 1);
}
//if original slop is 0 then require inOrder
boolean inorder = (mpq.getSlop() == 0);
return Collections.singletonList(new SpanNearQuery(positionSpanQueries, mpq.getSlop() + positionGaps, inorder));
} else if (query instanceof CommonTermsQuery) {
CommonTermsQuery ctq = (CommonTermsQuery) query;
List<Query> tqs = new ArrayList<>();
for (Term term : ctq.getTerms()) {
tqs.add(new TermQuery(term));
}
return tqs;
} else if (query instanceof AllTermQuery) {
AllTermQuery atq = (AllTermQuery) query;
return Collections.singletonList(new TermQuery(atq.getTerm()));
} else if (query instanceof FunctionScoreQuery) {
return Collections.singletonList(((FunctionScoreQuery) query).getSubQuery());
} else if (query instanceof FiltersFunctionScoreQuery) {
return Collections.singletonList(((FiltersFunctionScoreQuery) query).getSubQuery());
} else {
return null;
}
}
use of org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery in project elasticsearch by elastic.
the class FunctionScoreQueryBuilder method doToQuery.
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
FilterFunction[] filterFunctions = new FilterFunction[filterFunctionBuilders.length];
int i = 0;
for (FilterFunctionBuilder filterFunctionBuilder : filterFunctionBuilders) {
Query filter = filterFunctionBuilder.getFilter().toQuery(context);
ScoreFunction scoreFunction = filterFunctionBuilder.getScoreFunction().toFunction(context);
filterFunctions[i++] = new FilterFunction(filter, scoreFunction);
}
Query query = this.query.toQuery(context);
if (query == null) {
query = new MatchAllDocsQuery();
}
// handle cases where only one score function and no filter was provided. In this case we create a FunctionScoreQuery.
if (filterFunctions.length == 0 || filterFunctions.length == 1 && (this.filterFunctionBuilders[0].getFilter().getName().equals(MatchAllQueryBuilder.NAME))) {
ScoreFunction function = filterFunctions.length == 0 ? null : filterFunctions[0].function;
CombineFunction combineFunction = this.boostMode;
if (combineFunction == null) {
if (function != null) {
combineFunction = function.getDefaultScoreCombiner();
} else {
combineFunction = DEFAULT_BOOST_MODE;
}
}
return new FunctionScoreQuery(query, function, minScore, combineFunction, maxBoost);
}
// in all other cases we create a FiltersFunctionScoreQuery
CombineFunction boostMode = this.boostMode == null ? DEFAULT_BOOST_MODE : this.boostMode;
return new FiltersFunctionScoreQuery(query, scoreMode, filterFunctions, maxBoost, minScore, boostMode);
}
use of org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery in project elasticsearch by elastic.
the class FunctionScoreTests method testSimpleWeightedFunction.
public void testSimpleWeightedFunction() throws IOException, ExecutionException, InterruptedException {
int numFunctions = randomIntBetween(1, 3);
float[] weights = randomFloats(numFunctions);
double[] scores = randomDoubles(numFunctions);
ScoreFunctionStub[] scoreFunctionStubs = new ScoreFunctionStub[numFunctions];
for (int i = 0; i < numFunctions; i++) {
scoreFunctionStubs[i] = new ScoreFunctionStub(scores[i]);
}
WeightFactorFunction[] weightFunctionStubs = new WeightFactorFunction[numFunctions];
for (int i = 0; i < numFunctions; i++) {
weightFunctionStubs[i] = new WeightFactorFunction(weights[i], scoreFunctionStubs[i]);
}
FiltersFunctionScoreQuery filtersFunctionScoreQueryWithWeights = getFiltersFunctionScoreQuery(FiltersFunctionScoreQuery.ScoreMode.MULTIPLY, CombineFunction.REPLACE, weightFunctionStubs);
TopDocs topDocsWithWeights = searcher.search(filtersFunctionScoreQueryWithWeights, 1);
float scoreWithWeight = topDocsWithWeights.scoreDocs[0].score;
double score = 1;
for (int i = 0; i < weights.length; i++) {
score *= weights[i] * scores[i];
}
assertThat(scoreWithWeight / (float) score, is(1f));
float explainedScore = getExplanation(searcher, filtersFunctionScoreQueryWithWeights).getValue();
assertThat(explainedScore / scoreWithWeight, is(1f));
filtersFunctionScoreQueryWithWeights = getFiltersFunctionScoreQuery(FiltersFunctionScoreQuery.ScoreMode.SUM, CombineFunction.REPLACE, weightFunctionStubs);
topDocsWithWeights = searcher.search(filtersFunctionScoreQueryWithWeights, 1);
scoreWithWeight = topDocsWithWeights.scoreDocs[0].score;
double sum = 0;
for (int i = 0; i < weights.length; i++) {
sum += weights[i] * scores[i];
}
assertThat(scoreWithWeight / (float) sum, is(1f));
explainedScore = getExplanation(searcher, filtersFunctionScoreQueryWithWeights).getValue();
assertThat(explainedScore / scoreWithWeight, is(1f));
filtersFunctionScoreQueryWithWeights = getFiltersFunctionScoreQuery(FiltersFunctionScoreQuery.ScoreMode.AVG, CombineFunction.REPLACE, weightFunctionStubs);
topDocsWithWeights = searcher.search(filtersFunctionScoreQueryWithWeights, 1);
scoreWithWeight = topDocsWithWeights.scoreDocs[0].score;
double norm = 0;
sum = 0;
for (int i = 0; i < weights.length; i++) {
norm += weights[i];
sum += weights[i] * scores[i];
}
assertThat(scoreWithWeight / (float) (sum / norm), is(1f));
explainedScore = getExplanation(searcher, filtersFunctionScoreQueryWithWeights).getValue();
assertThat(explainedScore / scoreWithWeight, is(1f));
filtersFunctionScoreQueryWithWeights = getFiltersFunctionScoreQuery(FiltersFunctionScoreQuery.ScoreMode.MIN, CombineFunction.REPLACE, weightFunctionStubs);
topDocsWithWeights = searcher.search(filtersFunctionScoreQueryWithWeights, 1);
scoreWithWeight = topDocsWithWeights.scoreDocs[0].score;
double min = Double.POSITIVE_INFINITY;
for (int i = 0; i < weights.length; i++) {
min = Math.min(min, weights[i] * scores[i]);
}
assertThat(scoreWithWeight / (float) min, is(1f));
explainedScore = getExplanation(searcher, filtersFunctionScoreQueryWithWeights).getValue();
assertThat(explainedScore / scoreWithWeight, is(1f));
filtersFunctionScoreQueryWithWeights = getFiltersFunctionScoreQuery(FiltersFunctionScoreQuery.ScoreMode.MAX, CombineFunction.REPLACE, weightFunctionStubs);
topDocsWithWeights = searcher.search(filtersFunctionScoreQueryWithWeights, 1);
scoreWithWeight = topDocsWithWeights.scoreDocs[0].score;
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < weights.length; i++) {
max = Math.max(max, weights[i] * scores[i]);
}
assertThat(scoreWithWeight / (float) max, is(1f));
explainedScore = getExplanation(searcher, filtersFunctionScoreQueryWithWeights).getValue();
assertThat(explainedScore / scoreWithWeight, is(1f));
}
use of org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery in project elasticsearch by elastic.
the class FunctionScoreTests method testPropagatesApproximations.
public void testPropagatesApproximations() throws IOException {
Query query = new RandomApproximationQuery(new MatchAllDocsQuery(), random());
IndexSearcher searcher = newSearcher(reader);
// otherwise we could get a cached entry that does not have approximations
searcher.setQueryCache(null);
FunctionScoreQuery fsq = new FunctionScoreQuery(query, null, null, null, Float.POSITIVE_INFINITY);
for (boolean needsScores : new boolean[] { true, false }) {
Weight weight = searcher.createWeight(fsq, needsScores);
Scorer scorer = weight.scorer(reader.leaves().get(0));
assertNotNull(scorer.twoPhaseIterator());
}
FiltersFunctionScoreQuery ffsq = new FiltersFunctionScoreQuery(query, ScoreMode.SUM, new FilterFunction[0], Float.POSITIVE_INFINITY, null, CombineFunction.MULTIPLY);
for (boolean needsScores : new boolean[] { true, false }) {
Weight weight = searcher.createWeight(ffsq, needsScores);
Scorer scorer = weight.scorer(reader.leaves().get(0));
assertNotNull(scorer.twoPhaseIterator());
}
}
use of org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery in project elasticsearch by elastic.
the class FunctionScoreTests method testMinScoreExplain.
public void testMinScoreExplain() throws IOException {
Query query = new MatchAllDocsQuery();
Explanation queryExpl = searcher.explain(query, 0);
FunctionScoreQuery fsq = new FunctionScoreQuery(query, null, 0f, null, Float.POSITIVE_INFINITY);
Explanation fsqExpl = searcher.explain(fsq, 0);
assertTrue(fsqExpl.isMatch());
assertEquals(queryExpl.getValue(), fsqExpl.getValue(), 0f);
assertEquals(queryExpl.getDescription(), fsqExpl.getDescription());
fsq = new FunctionScoreQuery(query, null, 10f, null, Float.POSITIVE_INFINITY);
fsqExpl = searcher.explain(fsq, 0);
assertFalse(fsqExpl.isMatch());
assertEquals("Score value is too low, expected at least 10.0 but got 1.0", fsqExpl.getDescription());
FiltersFunctionScoreQuery ffsq = new FiltersFunctionScoreQuery(query, ScoreMode.SUM, new FilterFunction[0], Float.POSITIVE_INFINITY, 0f, CombineFunction.MULTIPLY);
Explanation ffsqExpl = searcher.explain(ffsq, 0);
assertTrue(ffsqExpl.isMatch());
assertEquals(queryExpl.getValue(), ffsqExpl.getValue(), 0f);
assertEquals(queryExpl.getDescription(), ffsqExpl.getDetails()[0].getDescription());
ffsq = new FiltersFunctionScoreQuery(query, ScoreMode.SUM, new FilterFunction[0], Float.POSITIVE_INFINITY, 10f, CombineFunction.MULTIPLY);
ffsqExpl = searcher.explain(ffsq, 0);
assertFalse(ffsqExpl.isMatch());
assertEquals("Score value is too low, expected at least 10.0 but got 1.0", ffsqExpl.getDescription());
}
Aggregations