⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disjunctionsumscorer.java

📁 Lucene a java open-source SearchEngine Framework
💻 JAVA
字号:
package org.apache.lucene.search;/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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. */import java.util.List;import java.util.Iterator;import java.io.IOException;import org.apache.lucene.util.ScorerDocQueue;/** A Scorer for OR like queries, counterpart of <code>ConjunctionScorer</code>. * This Scorer implements {@link Scorer#skipTo(int)} and uses skipTo() on the given Scorers.  * @todo Implement score(HitCollector, int). */class DisjunctionSumScorer extends Scorer {  /** The number of subscorers. */   private final int nrScorers;    /** The subscorers. */  protected final List subScorers;    /** The minimum number of scorers that should match. */  private final int minimumNrMatchers;    /** The scorerDocQueue contains all subscorers ordered by their current doc(),   * with the minimum at the top.   * <br>The scorerDocQueue is initialized the first time next() or skipTo() is called.   * <br>An exhausted scorer is immediately removed from the scorerDocQueue.   * <br>If less than the minimumNrMatchers scorers   * remain in the scorerDocQueue next() and skipTo() return false.   * <p>   * After each to call to next() or skipTo()   * <code>currentSumScore</code> is the total score of the current matching doc,   * <code>nrMatchers</code> is the number of matching scorers,   * and all scorers are after the matching doc, or are exhausted.   */  private ScorerDocQueue scorerDocQueue = null;  private int queueSize = -1; // used to avoid size() method calls on scorerDocQueue    /** The document number of the current match. */  private int currentDoc = -1;  /** The number of subscorers that provide the current match. */  protected int nrMatchers = -1;  private float currentScore = Float.NaN;    /** Construct a <code>DisjunctionScorer</code>.   * @param subScorers A collection of at least two subscorers.   * @param minimumNrMatchers The positive minimum number of subscorers that should   * match to match this query.   * <br>When <code>minimumNrMatchers</code> is bigger than   * the number of <code>subScorers</code>,   * no matches will be produced.   * <br>When minimumNrMatchers equals the number of subScorers,   * it more efficient to use <code>ConjunctionScorer</code>.   */  public DisjunctionSumScorer( List subScorers, int minimumNrMatchers) {    super(null);        nrScorers = subScorers.size();    if (minimumNrMatchers <= 0) {      throw new IllegalArgumentException("Minimum nr of matchers must be positive");    }    if (nrScorers <= 1) {      throw new IllegalArgumentException("There must be at least 2 subScorers");    }    this.minimumNrMatchers = minimumNrMatchers;    this.subScorers = subScorers;  }    /** Construct a <code>DisjunctionScorer</code>, using one as the minimum number   * of matching subscorers.   */  public DisjunctionSumScorer(List subScorers) {    this(subScorers, 1);  }  /** Called the first time next() or skipTo() is called to   * initialize <code>scorerDocQueue</code>.   */  private void initScorerDocQueue() throws IOException {    Iterator si = subScorers.iterator();    scorerDocQueue = new ScorerDocQueue(nrScorers);    queueSize = 0;    while (si.hasNext()) {      Scorer se = (Scorer) si.next();      if (se.next()) { // doc() method will be used in scorerDocQueue.        if (scorerDocQueue.insert(se)) {          queueSize++;        }      }    }  }  /** Scores and collects all matching documents.   * @param hc The collector to which all matching documents are passed through   * {@link HitCollector#collect(int, float)}.   * <br>When this method is used the {@link #explain(int)} method should not be used.   */  public void score(HitCollector hc) throws IOException {    while (next()) {      hc.collect(currentDoc, currentScore);    }  }  /** Expert: Collects matching documents in a range.  Hook for optimization.   * Note that {@link #next()} must be called once before this method is called   * for the first time.   * @param hc The collector to which all matching documents are passed through   * {@link HitCollector#collect(int, float)}.   * @param max Do not score documents past this.   * @return true if more matching documents may remain.   */  protected boolean score(HitCollector hc, int max) throws IOException {    while (currentDoc < max) {      hc.collect(currentDoc, currentScore);      if (!next()) {        return false;      }    }    return true;  }  public boolean next() throws IOException {    if (scorerDocQueue == null) {      initScorerDocQueue();    }    return (scorerDocQueue.size() >= minimumNrMatchers)          && advanceAfterCurrent();  }  /** Advance all subscorers after the current document determined by the   * top of the <code>scorerDocQueue</code>.   * Repeat until at least the minimum number of subscorers match on the same   * document and all subscorers are after that document or are exhausted.   * <br>On entry the <code>scorerDocQueue</code> has at least <code>minimumNrMatchers</code>   * available. At least the scorer with the minimum document number will be advanced.   * @return true iff there is a match.   * <br>In case there is a match, </code>currentDoc</code>, </code>currentSumScore</code>,   * and </code>nrMatchers</code> describe the match.   *   * @todo Investigate whether it is possible to use skipTo() when   * the minimum number of matchers is bigger than one, ie. try and use the   * character of ConjunctionScorer for the minimum number of matchers.   * Also delay calling score() on the sub scorers until the minimum number of   * matchers is reached.   * <br>For this, a Scorer array with minimumNrMatchers elements might   * hold Scorers at currentDoc that are temporarily popped from scorerQueue.   */  protected boolean advanceAfterCurrent() throws IOException {    do { // repeat until minimum nr of matchers      currentDoc = scorerDocQueue.topDoc();      currentScore = scorerDocQueue.topScore();      nrMatchers = 1;      do { // Until all subscorers are after currentDoc        if (! scorerDocQueue.topNextAndAdjustElsePop()) {          if (--queueSize == 0) {            break; // nothing more to advance, check for last match.          }        }        if (scorerDocQueue.topDoc() != currentDoc) {          break; // All remaining subscorers are after currentDoc.        }        currentScore += scorerDocQueue.topScore();        nrMatchers++;      } while (true);            if (nrMatchers >= minimumNrMatchers) {        return true;      } else if (queueSize < minimumNrMatchers) {        return false;      }    } while (true);  }    /** Returns the score of the current document matching the query.   * Initially invalid, until {@link #next()} is called the first time.   */  public float score() throws IOException { return currentScore; }     public int doc() { return currentDoc; }  /** Returns the number of subscorers matching the current document.   * Initially invalid, until {@link #next()} is called the first time.   */  public int nrMatchers() {    return nrMatchers;  }  /** Skips to the first match beyond the current whose document number is   * greater than or equal to a given target.   * <br>When this method is used the {@link #explain(int)} method should not be used.   * <br>The implementation uses the skipTo() method on the subscorers.   * @param target The target document number.   * @return true iff there is such a match.   */  public boolean skipTo(int target) throws IOException {    if (scorerDocQueue == null) {      initScorerDocQueue();    }    if (queueSize < minimumNrMatchers) {      return false;    }    if (target <= currentDoc) {      return true;    }    do {      if (scorerDocQueue.topDoc() >= target) {        return advanceAfterCurrent();      } else if (! scorerDocQueue.topSkipToAndAdjustElsePop(target)) {        if (--queueSize < minimumNrMatchers) {          return false;        }      }    } while (true);  }  /** @return An explanation for the score of a given document. */  public Explanation explain(int doc) throws IOException {    Explanation res = new Explanation();    Iterator ssi = subScorers.iterator();    float sumScore = 0.0f;    int nrMatches = 0;    while (ssi.hasNext()) {      Explanation es = ((Scorer) ssi.next()).explain(doc);      if (es.getValue() > 0.0f) { // indicates match        sumScore += es.getValue();        nrMatches++;      }      res.addDetail(es);    }    if (nrMatchers >= minimumNrMatchers) {      res.setValue(sumScore);      res.setDescription("sum over at least " + minimumNrMatchers                         + " of " + subScorers.size() + ":");    } else {      res.setValue(0.0f);      res.setDescription(nrMatches + " match(es) but at least "                         + minimumNrMatchers + " of "                         + subScorers.size() + " needed");    }    return res;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -