Search in sources :

Example 1 with ExplanationHolder

use of org.opensearch.script.ScoreScript.ExplanationHolder in project OpenSearch by opensearch-project.

the class ScriptScoreQuery method createWeight.

@Override
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
    if (scoreMode == ScoreMode.COMPLETE_NO_SCORES && minScore == null) {
        return subQuery.createWeight(searcher, scoreMode, boost);
    }
    boolean needsScore = scriptBuilder.needs_score();
    ScoreMode subQueryScoreMode = needsScore ? ScoreMode.COMPLETE : ScoreMode.COMPLETE_NO_SCORES;
    Weight subQueryWeight = subQuery.createWeight(searcher, subQueryScoreMode, 1.0f);
    return new Weight(this) {

        @Override
        public BulkScorer bulkScorer(LeafReaderContext context) throws IOException {
            if (minScore == null) {
                final BulkScorer subQueryBulkScorer = subQueryWeight.bulkScorer(context);
                if (subQueryBulkScorer == null) {
                    return null;
                }
                return new ScriptScoreBulkScorer(subQueryBulkScorer, subQueryScoreMode, makeScoreScript(context), boost);
            } else {
                return super.bulkScorer(context);
            }
        }

        @Override
        public void extractTerms(Set<Term> terms) {
            subQueryWeight.extractTerms(terms);
        }

        @Override
        public Scorer scorer(LeafReaderContext context) throws IOException {
            Scorer subQueryScorer = subQueryWeight.scorer(context);
            if (subQueryScorer == null) {
                return null;
            }
            Scorer scriptScorer = new ScriptScorer(this, makeScoreScript(context), subQueryScorer, subQueryScoreMode, boost, null);
            if (minScore != null) {
                scriptScorer = new MinScoreScorer(this, scriptScorer, minScore);
            }
            return scriptScorer;
        }

        @Override
        public Explanation explain(LeafReaderContext context, int doc) throws IOException {
            Explanation subQueryExplanation = Functions.explainWithName(subQueryWeight.explain(context, doc), queryName);
            if (subQueryExplanation.isMatch() == false) {
                return subQueryExplanation;
            }
            ExplanationHolder explanationHolder = new ExplanationHolder();
            Scorer scorer = new ScriptScorer(this, makeScoreScript(context), subQueryWeight.scorer(context), subQueryScoreMode, 1f, explanationHolder);
            int newDoc = scorer.iterator().advance(doc);
            // subquery should have already matched above
            assert doc == newDoc;
            // score without boost
            float score = scorer.score();
            Explanation explanation = explanationHolder.get(score, needsScore ? subQueryExplanation : null);
            if (explanation == null) {
                // no explanation provided by user; give a simple one
                String desc = "script score function, computed with script:\"" + script + "\"";
                if (needsScore) {
                    Explanation scoreExp = Explanation.match(subQueryExplanation.getValue(), "_score: ", subQueryExplanation);
                    explanation = Explanation.match(score, desc, scoreExp);
                } else {
                    explanation = Explanation.match(score, desc);
                }
            }
            if (boost != 1f) {
                explanation = Explanation.match(boost * explanation.getValue().floatValue(), "Boosted score, product of:", Explanation.match(boost, "boost"), explanation);
            }
            if (minScore != null && minScore > explanation.getValue().floatValue()) {
                explanation = Explanation.noMatch("Score value is too low, expected at least " + minScore + " but got " + explanation.getValue(), explanation);
            }
            return explanation;
        }

        private ScoreScript makeScoreScript(LeafReaderContext context) throws IOException {
            final ScoreScript scoreScript = scriptBuilder.newInstance(context);
            scoreScript._setIndexName(indexName);
            scoreScript._setShard(shardId);
            scoreScript._setIndexVersion(indexVersion);
            return scoreScript;
        }

        @Override
        public boolean isCacheable(LeafReaderContext ctx) {
            // If minScore is not null, then matches depend on statistics of the top-level reader.
            return minScore == null;
        }
    };
}
Also used : ScoreMode(org.apache.lucene.search.ScoreMode) Set(java.util.Set) ScoreScript(org.opensearch.script.ScoreScript) Explanation(org.apache.lucene.search.Explanation) BulkScorer(org.apache.lucene.search.BulkScorer) Scorer(org.apache.lucene.search.Scorer) ExplanationHolder(org.opensearch.script.ScoreScript.ExplanationHolder) BulkScorer(org.apache.lucene.search.BulkScorer) Weight(org.apache.lucene.search.Weight) LeafReaderContext(org.apache.lucene.index.LeafReaderContext)

Aggregations

Set (java.util.Set)1 LeafReaderContext (org.apache.lucene.index.LeafReaderContext)1 BulkScorer (org.apache.lucene.search.BulkScorer)1 Explanation (org.apache.lucene.search.Explanation)1 ScoreMode (org.apache.lucene.search.ScoreMode)1 Scorer (org.apache.lucene.search.Scorer)1 Weight (org.apache.lucene.search.Weight)1 ScoreScript (org.opensearch.script.ScoreScript)1 ExplanationHolder (org.opensearch.script.ScoreScript.ExplanationHolder)1