@Override
    public Explanation explain(LeafReaderContext context, int doc) throws IOException {

      Explanation expl = subQueryWeight.explain(context, doc);
      if (!expl.isMatch()) {
        return expl;
      }
      // First: Gather explanations for all filters
      List<Explanation> filterExplanations = new ArrayList<>();
      for (int i = 0; i < filterFunctions.length; ++i) {
        Bits docSet =
            Lucene.asSequentialAccessBits(
                context.reader().maxDoc(), filterWeights[i].scorer(context));
        if (docSet.get(doc)) {
          FilterFunction filterFunction = filterFunctions[i];
          Explanation functionExplanation =
              filterFunction.function.getLeafScoreFunction(context).explainScore(doc, expl);
          double factor = functionExplanation.getValue();
          float sc = CombineFunction.toFloat(factor);
          Explanation filterExplanation =
              Explanation.match(
                  sc,
                  "function score, product of:",
                  Explanation.match(1.0f, "match filter: " + filterFunction.filter.toString()),
                  functionExplanation);
          filterExplanations.add(filterExplanation);
        }
      }
      if (filterExplanations.size() > 0) {
        FiltersFunctionFactorScorer scorer = functionScorer(context);
        int actualDoc = scorer.iterator().advance(doc);
        assert (actualDoc == doc);
        double score = scorer.computeScore(doc, expl.getValue());
        Explanation factorExplanation =
            Explanation.match(
                CombineFunction.toFloat(score),
                "function score, score mode ["
                    + scoreMode.toString().toLowerCase(Locale.ROOT)
                    + "]",
                filterExplanations);
        expl = combineFunction.explain(expl, factorExplanation, maxBoost);
      }
      if (minScore != null && minScore > expl.getValue()) {
        expl =
            Explanation.noMatch(
                "Score value is too low, expected at least "
                    + minScore
                    + " but got "
                    + expl.getValue(),
                expl);
      }
      return expl;
    }
 @Override
 protected Explanation explain(int doc) throws IOException {
   Explanation result = new Explanation();
   // Add detail about tf/idf...
   Explanation nonPayloadExpl = super.explain(doc);
   result.addDetail(nonPayloadExpl);
   // Add detail about payload
   Explanation payloadExpl = function.explain(doc, payloadsSeen, payloadScore);
   result.addDetail(payloadExpl);
   result.setValue(nonPayloadExpl.getValue() * payloadExpl.getValue());
   result.setDescription("PayloadNearQuery, product of:");
   return result;
 }
 /*     */ public Explanation customExplain(
     int doc, Explanation subQueryExpl, Explanation valSrcExpl)
     /*     */ throws IOException
       /*     */ {
   /* 154 */ float valSrcScore = 1.0F;
   /* 155 */ if (valSrcExpl != null) {
     /* 156 */ valSrcScore *= valSrcExpl.getValue();
     /*     */ }
   /* 158 */ Explanation exp =
       new Explanation(valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
   /* 159 */ exp.addDetail(subQueryExpl);
   /* 160 */ exp.addDetail(valSrcExpl);
   /* 161 */ return exp;
   /*     */ }
  @Override
  public Explanation explain(AtomicReaderContext context, int doc) throws IOException {
    Scorer scorer = scorer(context, true, false, context.reader().getLiveDocs());
    if (scorer != null) {
      int newDoc = scorer.advance(doc);
      if (newDoc == doc) {
        float freq = scorer.freq();
        SloppySimScorer docScorer = similarity.sloppySimScorer(stats, context);
        ComplexExplanation result = new ComplexExplanation();
        result.setDescription(
            "weight("
                + getQuery()
                + " in "
                + doc
                + ") ["
                + similarity.getClass().getSimpleName()
                + "], result of:");
        Explanation scoreExplanation =
            docScorer.explain(doc, new Explanation(freq, "phraseFreq=" + freq));
        result.addDetail(scoreExplanation);
        result.setValue(scoreExplanation.getValue());
        result.setMatch(true);
        return result;
      }
    }

    return new ComplexExplanation(false, 0.0f, "no matching term");
  }
 @Override
 public Explanation explain(int docId, Explanation subQueryExpl) {
   float score = score(docId, subQueryExpl.getValue());
   Explanation exp = new Explanation(score, "script score function: product of:");
   exp.addDetail(subQueryExpl);
   return exp;
 }
 @Override
 public Explanation explain(int doc, Explanation freq) {
   Explanation expl = new Explanation(score(doc, freq.getValue()), "sum of:");
   for (SimScorer subScorer : subScorers) {
     expl.addDetail(subScorer.explain(doc, freq));
   }
   return expl;
 }
Exemple #7
0
 boolean findPayloadBoostInExplanation(Explanation expl) {
   if (expl.getDescription().startsWith("payloadBoost=") && expl.getValue() != 1f) {
     return true;
   } else {
     boolean found = false;
     for (Explanation sub : expl.getDetails()) {
       found |= findPayloadBoostInExplanation(sub);
     }
     return found;
   }
 }
      @Override
      protected Explanation explain(final int doc) throws IOException {
        ComplexExplanation result = new ComplexExplanation();
        Explanation nonPayloadExpl = super.explain(doc);
        result.addDetail(nonPayloadExpl);
        // QUESTION: Is there a way to avoid this skipTo call? We need to know
        // whether to load the payload or not
        Explanation payloadBoost = new Explanation();
        result.addDetail(payloadBoost);

        float payloadScore = getPayloadScore();
        payloadBoost.setValue(payloadScore);
        // GSI: I suppose we could toString the payload, but I don't think that
        // would be a good idea
        payloadBoost.setDescription("scorePayload(...)");
        result.setValue(nonPayloadExpl.getValue() * payloadScore);
        result.setDescription("btq, product of:");
        result.setMatch(
            nonPayloadExpl.getValue() == 0 ? Boolean.FALSE : Boolean.TRUE); // LUCENE-1303
        return result;
      }
 public Explanation explain(int doc) throws IOException {
   Explanation subQueryExpl = weight.qWeight.explain(reader, doc);
   if (!subQueryExpl.isMatch()) {
     return subQueryExpl;
   }
   float sc = subQueryExpl.getValue() * vals.floatVal(doc);
   Explanation res =
       new ComplexExplanation(true, sc, BoostedQuery.this.toString() + ", product of:");
   res.addDetail(subQueryExpl);
   res.addDetail(vals.explain(doc));
   return res;
 }
    public Explanation explain(IndexReader reader, int doc) throws IOException {
      ComplexExplanation result = new ComplexExplanation();
      result.setDescription("weight(" + getQuery() + " in " + doc + "), product of:");

      Explanation idfExpl = new Explanation(idf, "idf(docFreq=" + reader.docFreq(term) + ")");

      // explain query weight
      Explanation queryExpl = new Explanation();
      queryExpl.setDescription("queryWeight(" + getQuery() + "), product of:");

      Explanation boostExpl = new Explanation(getBoost(), "boost");
      if (getBoost() != 1.0f) queryExpl.addDetail(boostExpl);
      queryExpl.addDetail(idfExpl);

      Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
      queryExpl.addDetail(queryNormExpl);

      queryExpl.setValue(boostExpl.getValue() * idfExpl.getValue() * queryNormExpl.getValue());

      result.addDetail(queryExpl);

      // explain field weight
      String field = term.field();
      ComplexExplanation fieldExpl = new ComplexExplanation();
      fieldExpl.setDescription("fieldWeight(" + term + " in " + doc + "), product of:");

      Explanation tfExpl = scorer(reader).explain(doc);
      fieldExpl.addDetail(tfExpl);
      fieldExpl.addDetail(idfExpl);

      Explanation fieldNormExpl = new Explanation();
      byte[] fieldNorms = reader.norms(field);
      float fieldNorm = fieldNorms != null ? Similarity.decodeNorm(fieldNorms[doc]) : 0.0f;
      fieldNormExpl.setValue(fieldNorm);
      fieldNormExpl.setDescription("fieldNorm(field=" + field + ", doc=" + doc + ")");
      fieldExpl.addDetail(fieldNormExpl);

      fieldExpl.setMatch(Boolean.valueOf(tfExpl.isMatch()));
      fieldExpl.setValue(tfExpl.getValue() * idfExpl.getValue() * fieldNormExpl.getValue());

      result.addDetail(fieldExpl);
      result.setMatch(fieldExpl.getMatch());

      // combine them
      result.setValue(queryExpl.getValue() * fieldExpl.getValue());

      if (queryExpl.getValue() == 1.0f) return fieldExpl;

      return result;
    }
 public static void writeExplanation(StreamOutput out, Explanation explanation)
     throws IOException {
   out.writeFloat(explanation.getValue());
   out.writeString(explanation.getDescription());
   Explanation[] subExplanations = explanation.getDetails();
   if (subExplanations == null) {
     out.writeBoolean(false);
   } else {
     out.writeBoolean(true);
     out.writeVInt(subExplanations.length);
     for (Explanation subExp : subExplanations) {
       writeExplanation(out, subExp);
     }
   }
 }
 private void buildExplanation(XContentBuilder builder, Explanation explanation)
     throws IOException {
   builder.startObject();
   builder.field(Fields.VALUE, explanation.getValue());
   builder.field(Fields.DESCRIPTION, explanation.getDescription());
   Explanation[] innerExps = explanation.getDetails();
   if (innerExps != null) {
     builder.startArray(Fields.DETAILS);
     for (Explanation exp : innerExps) {
       buildExplanation(builder, exp);
     }
     builder.endArray();
   }
   builder.endObject();
 }
Exemple #13
0
  @Override
  protected Explanation createExplain(Explanation innerExplain, IndexReader reader, int doc)
      throws IOException {
    if (reader instanceof BoboIndexReader) {
      Explanation finalExpl = new Explanation();
      finalExpl.addDetail(innerExplain);

      _func.initializeReader((BoboIndexReader) reader, _jsonParam);

      float innerValue = innerExplain.getValue();
      float value = 0;
      if (_func.useInnerScore()) value = _func.newScore(innerValue, doc);
      else value = _func.newScore(doc);

      finalExpl.setValue(value);
      finalExpl.setDescription("Custom score: " + _func.getExplainString(innerValue, doc));
      return finalExpl;
    } else {
      throw new IllegalStateException("reader not instance of " + BoboIndexReader.class);
    }
  }
    @Override
    public Explanation explain(IndexReader reader, int doc) throws IOException {
      SolrIndexReader topReader = (SolrIndexReader) reader;
      SolrIndexReader[] subReaders = topReader.getLeafReaders();
      int[] offsets = topReader.getLeafOffsets();
      int readerPos = SolrIndexReader.readerIndex(doc, offsets);
      int readerBase = offsets[readerPos];

      Explanation subQueryExpl = qWeight.explain(reader, doc);
      if (!subQueryExpl.isMatch()) {
        return subQueryExpl;
      }

      DocValues vals = boostVal.getValues(context, subReaders[readerPos]);
      float sc = subQueryExpl.getValue() * vals.floatVal(doc - readerBase);
      Explanation res =
          new ComplexExplanation(true, sc, BoostedQuery.this.toString() + ", product of:");
      res.addDetail(subQueryExpl);
      res.addDetail(vals.explain(doc - readerBase));
      return res;
    }
 /*     */ public Explanation customExplain(
     int doc, Explanation subQueryExpl, Explanation[] valSrcExpls)
     /*     */ throws IOException
       /*     */ {
   /* 124 */ if (valSrcExpls.length == 1) {
     /* 125 */ return customExplain(doc, subQueryExpl, valSrcExpls[0]);
     /*     */ }
   /* 127 */ if (valSrcExpls.length == 0) {
     /* 128 */ return subQueryExpl;
     /*     */ }
   /* 130 */ float valSrcScore = 1.0F;
   /* 131 */ for (int i = 0; i < valSrcExpls.length; i++) {
     /* 132 */ valSrcScore *= valSrcExpls[i].getValue();
     /*     */ }
   /* 134 */ Explanation exp =
       new Explanation(valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
   /* 135 */ exp.addDetail(subQueryExpl);
   /* 136 */ for (int i = 0; i < valSrcExpls.length; i++) {
     /* 137 */ exp.addDetail(valSrcExpls[i]);
     /*     */ }
   /* 139 */ return exp;
   /*     */ }
 private Explanation doExplain(IndexReader reader, int doc) throws IOException {
   Explanation subQueryExpl = subQueryWeight.explain(reader, doc);
   if (!subQueryExpl.isMatch()) {
     return subQueryExpl;
   }
   // match
   Explanation[] valSrcExpls = new Explanation[valSrcWeights.length];
   for (int i = 0; i < valSrcWeights.length; i++) {
     valSrcExpls[i] = valSrcWeights[i].explain(reader, doc);
   }
   Explanation customExp =
       CustomScoreQuery.this
           .getCustomScoreProvider(reader)
           .customExplain(doc, subQueryExpl, valSrcExpls);
   float sc = getValue() * customExp.getValue();
   Explanation res =
       new ComplexExplanation(true, sc, CustomScoreQuery.this.toString() + ", product of:");
   res.addDetail(customExp);
   res.addDetail(
       new Explanation(
           getValue(),
           "queryBoost")); // actually using the q boost as q weight (== weight value)
   return res;
 }
 /** not a direct test of NearSpans, but a demonstration of how/when this causes problems */
 public void testSpanNearScorerExplain() throws Exception {
   SpanNearQuery q = makeQuery();
   Explanation e = q.weight(searcher).explain(searcher.getIndexReader(), 1);
   assertTrue(
       "Scorer explanation value for doc#1 isn't positive: " + e.toString(), 0.0f < e.getValue());
 }
Exemple #18
0
  private void executeRandomJoin(
      boolean multipleValuesPerDocument,
      int maxIndexIter,
      int maxSearchIter,
      int numberOfDocumentsToIndex)
      throws Exception {
    for (int indexIter = 1; indexIter <= maxIndexIter; indexIter++) {
      if (VERBOSE) {
        System.out.println("indexIter=" + indexIter);
      }
      Directory dir = newDirectory();
      RandomIndexWriter w =
          new RandomIndexWriter(
              random(),
              dir,
              newIndexWriterConfig(
                      TEST_VERSION_CURRENT,
                      new MockAnalyzer(random(), MockTokenizer.KEYWORD, false))
                  .setMergePolicy(newLogMergePolicy()));
      final boolean scoreDocsInOrder = TestJoinUtil.random().nextBoolean();
      IndexIterationContext context =
          createContext(numberOfDocumentsToIndex, w, multipleValuesPerDocument, scoreDocsInOrder);

      IndexReader topLevelReader = w.getReader();
      w.close();
      for (int searchIter = 1; searchIter <= maxSearchIter; searchIter++) {
        if (VERBOSE) {
          System.out.println("searchIter=" + searchIter);
        }
        IndexSearcher indexSearcher = newSearcher(topLevelReader);

        int r = random().nextInt(context.randomUniqueValues.length);
        boolean from = context.randomFrom[r];
        String randomValue = context.randomUniqueValues[r];
        FixedBitSet expectedResult =
            createExpectedResult(randomValue, from, indexSearcher.getIndexReader(), context);

        final Query actualQuery = new TermQuery(new Term("value", randomValue));
        if (VERBOSE) {
          System.out.println("actualQuery=" + actualQuery);
        }
        final ScoreMode scoreMode = ScoreMode.values()[random().nextInt(ScoreMode.values().length)];
        if (VERBOSE) {
          System.out.println("scoreMode=" + scoreMode);
        }

        final Query joinQuery;
        if (from) {
          joinQuery =
              JoinUtil.createJoinQuery(
                  "from", multipleValuesPerDocument, "to", actualQuery, indexSearcher, scoreMode);
        } else {
          joinQuery =
              JoinUtil.createJoinQuery(
                  "to", multipleValuesPerDocument, "from", actualQuery, indexSearcher, scoreMode);
        }
        if (VERBOSE) {
          System.out.println("joinQuery=" + joinQuery);
        }

        // Need to know all documents that have matches. TopDocs doesn't give me that and then I'd
        // be also testing TopDocsCollector...
        final FixedBitSet actualResult = new FixedBitSet(indexSearcher.getIndexReader().maxDoc());
        final TopScoreDocCollector topScoreDocCollector = TopScoreDocCollector.create(10, false);
        indexSearcher.search(
            joinQuery,
            new Collector() {

              int docBase;

              @Override
              public void collect(int doc) throws IOException {
                actualResult.set(doc + docBase);
                topScoreDocCollector.collect(doc);
              }

              @Override
              public void setNextReader(AtomicReaderContext context) {
                docBase = context.docBase;
                topScoreDocCollector.setNextReader(context);
              }

              @Override
              public void setScorer(Scorer scorer) throws IOException {
                topScoreDocCollector.setScorer(scorer);
              }

              @Override
              public boolean acceptsDocsOutOfOrder() {
                return scoreDocsInOrder;
              }
            });
        // Asserting bit set...
        if (VERBOSE) {
          System.out.println("expected cardinality:" + expectedResult.cardinality());
          DocIdSetIterator iterator = expectedResult.iterator();
          for (int doc = iterator.nextDoc();
              doc != DocIdSetIterator.NO_MORE_DOCS;
              doc = iterator.nextDoc()) {
            System.out.println(
                String.format(
                    Locale.ROOT,
                    "Expected doc[%d] with id value %s",
                    doc,
                    indexSearcher.doc(doc).get("id")));
          }
          System.out.println("actual cardinality:" + actualResult.cardinality());
          iterator = actualResult.iterator();
          for (int doc = iterator.nextDoc();
              doc != DocIdSetIterator.NO_MORE_DOCS;
              doc = iterator.nextDoc()) {
            System.out.println(
                String.format(
                    Locale.ROOT,
                    "Actual doc[%d] with id value %s",
                    doc,
                    indexSearcher.doc(doc).get("id")));
          }
        }
        assertEquals(expectedResult, actualResult);

        // Asserting TopDocs...
        TopDocs expectedTopDocs = createExpectedTopDocs(randomValue, from, scoreMode, context);
        TopDocs actualTopDocs = topScoreDocCollector.topDocs();
        assertEquals(expectedTopDocs.totalHits, actualTopDocs.totalHits);
        assertEquals(expectedTopDocs.scoreDocs.length, actualTopDocs.scoreDocs.length);
        if (scoreMode == ScoreMode.None) {
          continue;
        }

        assertEquals(expectedTopDocs.getMaxScore(), actualTopDocs.getMaxScore(), 0.0f);
        for (int i = 0; i < expectedTopDocs.scoreDocs.length; i++) {
          if (VERBOSE) {
            System.out.printf(
                Locale.ENGLISH,
                "Expected doc: %d | Actual doc: %d\n",
                expectedTopDocs.scoreDocs[i].doc,
                actualTopDocs.scoreDocs[i].doc);
            System.out.printf(
                Locale.ENGLISH,
                "Expected score: %f | Actual score: %f\n",
                expectedTopDocs.scoreDocs[i].score,
                actualTopDocs.scoreDocs[i].score);
          }
          assertEquals(expectedTopDocs.scoreDocs[i].doc, actualTopDocs.scoreDocs[i].doc);
          assertEquals(expectedTopDocs.scoreDocs[i].score, actualTopDocs.scoreDocs[i].score, 0.0f);
          Explanation explanation =
              indexSearcher.explain(joinQuery, expectedTopDocs.scoreDocs[i].doc);
          assertEquals(expectedTopDocs.scoreDocs[i].score, explanation.getValue(), 0.0f);
        }
      }
      topLevelReader.close();
      dir.close();
    }
  }