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

📄 booleanscorer2.java

📁 lucene2.2.0版本
💻 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.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Iterator;/** An alternative to BooleanScorer that also allows a minimum number * of optional scorers that should match. * <br>Implements skipTo(), and has no limitations on the numbers of added scorers. * <br>Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer. */class BooleanScorer2 extends Scorer {  private ArrayList requiredScorers = new ArrayList();  private ArrayList optionalScorers = new ArrayList();  private ArrayList prohibitedScorers = new ArrayList();  private class Coordinator {    int maxCoord = 0; // to be increased for each non prohibited scorer        private float[] coordFactors = null;        void init() { // use after all scorers have been added.      coordFactors = new float[maxCoord + 1];      Similarity sim = getSimilarity();      for (int i = 0; i <= maxCoord; i++) {        coordFactors[i] = sim.coord(i, maxCoord);      }    }        int nrMatchers; // to be increased by score() of match counting scorers.    void initDoc() {      nrMatchers = 0;    }        float coordFactor() {      return coordFactors[nrMatchers];    }  }  private final Coordinator coordinator;  /** The scorer to which all scoring will be delegated,   * except for computing and using the coordination factor.   */  private Scorer countingSumScorer = null;  /** The number of optionalScorers that need to match (if there are any) */  private final int minNrShouldMatch;    /** Whether it is allowed to return documents out of order.   *  This can accelerate the scoring of disjunction queries.     */    private boolean allowDocsOutOfOrder;  /** Create a BooleanScorer2.   * @param similarity The similarity to be used.   * @param minNrShouldMatch The minimum number of optional added scorers   *                         that should match during the search.   *                         In case no required scorers are added,   *                         at least one of the optional scorers will have to   *                         match during the search.   * @param allowDocsOutOfOrder Whether it is allowed to return documents out of order.   *                            This can accelerate the scoring of disjunction queries.                            */  public BooleanScorer2(Similarity similarity, int minNrShouldMatch, boolean allowDocsOutOfOrder) {    super(similarity);    if (minNrShouldMatch < 0) {      throw new IllegalArgumentException("Minimum number of optional scorers should not be negative");    }    coordinator = new Coordinator();    this.minNrShouldMatch = minNrShouldMatch;    this.allowDocsOutOfOrder = allowDocsOutOfOrder;  }  /** Create a BooleanScorer2.   *  In no required scorers are added,   *  at least one of the optional scorers will have to match during the search.   * @param similarity The similarity to be used.   * @param minNrShouldMatch The minimum number of optional added scorers   *                         that should match during the search.   *                         In case no required scorers are added,   *                         at least one of the optional scorers will have to   *                         match during the search.   */  public BooleanScorer2(Similarity similarity, int minNrShouldMatch) {    this(similarity, minNrShouldMatch, false);  }    /** Create a BooleanScorer2.   *  In no required scorers are added,   *  at least one of the optional scorers will have to match during the search.   * @param similarity The similarity to be used.   */  public BooleanScorer2(Similarity similarity) {    this(similarity, 0, false);  }  public void add(final Scorer scorer, boolean required, boolean prohibited) {    if (!prohibited) {      coordinator.maxCoord++;    }    if (required) {      if (prohibited) {        throw new IllegalArgumentException("scorer cannot be required and prohibited");      }      requiredScorers.add(scorer);    } else if (prohibited) {      prohibitedScorers.add(scorer);    } else {      optionalScorers.add(scorer);    }  }  /** Initialize the match counting scorer that sums all the   * scores. <p>   * When "counting" is used in a name it means counting the number   * of matching scorers.<br>   * When "sum" is used in a name it means score value summing   * over the matching scorers   */  private void initCountingSumScorer() {    coordinator.init();    countingSumScorer = makeCountingSumScorer();  }  /** Count a scorer as a single match. */  private class SingleMatchScorer extends Scorer {    private Scorer scorer;    private int lastScoredDoc = -1;    SingleMatchScorer(Scorer scorer) {      super(scorer.getSimilarity());      this.scorer = scorer;    }    public float score() throws IOException {      if (this.doc() >= lastScoredDoc) {        lastScoredDoc = this.doc();        coordinator.nrMatchers++;      }      return scorer.score();    }    public int doc() {      return scorer.doc();    }    public boolean next() throws IOException {      return scorer.next();    }    public boolean skipTo(int docNr) throws IOException {      return scorer.skipTo(docNr);    }    public Explanation explain(int docNr) throws IOException {      return scorer.explain(docNr);    }  }  private Scorer countingDisjunctionSumScorer(final List scorers,                                              int minNrShouldMatch)  // each scorer from the list counted as a single matcher  {    return new DisjunctionSumScorer(scorers, minNrShouldMatch) {      private int lastScoredDoc = -1;      public float score() throws IOException {        if (this.doc() >= lastScoredDoc) {          lastScoredDoc = this.doc();          coordinator.nrMatchers += super.nrMatchers;        }        return super.score();      }    };  }  private static Similarity defaultSimilarity = new DefaultSimilarity();  private Scorer countingConjunctionSumScorer(List requiredScorers) {    // each scorer from the list counted as a single matcher    final int requiredNrMatchers = requiredScorers.size();    ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity) {      private int lastScoredDoc = -1;      public float score() throws IOException {        if (this.doc() >= lastScoredDoc) {          lastScoredDoc = this.doc();          coordinator.nrMatchers += requiredNrMatchers;        }        // All scorers match, so defaultSimilarity super.score() always has 1 as        // the coordination factor.        // Therefore the sum of the scores of the requiredScorers        // is used as score.        return super.score();      }    };    Iterator rsi = requiredScorers.iterator();    while (rsi.hasNext()) {      cs.add((Scorer) rsi.next());    }    return cs;  }  private Scorer dualConjunctionSumScorer(Scorer req1, Scorer req2) { // non counting.     ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity);    // All scorers match, so defaultSimilarity always has 1 as    // the coordination factor.    // Therefore the sum of the scores of two scorers    // is used as score.    cs.add(req1);    cs.add(req2);    return cs;  }  /** Returns the scorer to be used for match counting and score summing.   * Uses requiredScorers, optionalScorers and prohibitedScorers.   */  private Scorer makeCountingSumScorer() { // each scorer counted as a single matcher    return (requiredScorers.size() == 0)          ? makeCountingSumScorerNoReq()          : makeCountingSumScorerSomeReq();  }  private Scorer makeCountingSumScorerNoReq() { // No required scorers    if (optionalScorers.size() == 0) {      return new NonMatchingScorer(); // no clauses or only prohibited clauses    } else { // No required scorers. At least one optional scorer.      // minNrShouldMatch optional scorers are required, but at least 1      int nrOptRequired = (minNrShouldMatch < 1) ? 1 : minNrShouldMatch;      if (optionalScorers.size() < nrOptRequired) {         return new NonMatchingScorer(); // fewer optional clauses than minimum (at least 1) that should match      } else { // optionalScorers.size() >= nrOptRequired, no required scorers        Scorer requiredCountingSumScorer =              (optionalScorers.size() > nrOptRequired)              ? countingDisjunctionSumScorer(optionalScorers, nrOptRequired)              : // optionalScorers.size() == nrOptRequired (all optional scorers are required), no required scorers              (optionalScorers.size() == 1)              ? new SingleMatchScorer((Scorer) optionalScorers.get(0))              : countingConjunctionSumScorer(optionalScorers);        return addProhibitedScorers(requiredCountingSumScorer);      }    }  }  private Scorer makeCountingSumScorerSomeReq() { // At least one required scorer.    if (optionalScorers.size() < minNrShouldMatch) {      return new NonMatchingScorer(); // fewer optional clauses than minimum that should match    } else if (optionalScorers.size() == minNrShouldMatch) { // all optional scorers also required.      ArrayList allReq = new ArrayList(requiredScorers);      allReq.addAll(optionalScorers);      return addProhibitedScorers(countingConjunctionSumScorer(allReq));    } else { // optionalScorers.size() > minNrShouldMatch, and at least one required scorer      Scorer requiredCountingSumScorer =            (requiredScorers.size() == 1)            ? new SingleMatchScorer((Scorer) requiredScorers.get(0))            : countingConjunctionSumScorer(requiredScorers);      if (minNrShouldMatch > 0) { // use a required disjunction scorer over the optional scorers        return addProhibitedScorers(                       dualConjunctionSumScorer( // non counting                              requiredCountingSumScorer,                              countingDisjunctionSumScorer(                                      optionalScorers,                                      minNrShouldMatch)));      } else { // minNrShouldMatch == 0        return new ReqOptSumScorer(                      addProhibitedScorers(requiredCountingSumScorer),                      ((optionalScorers.size() == 1)                        ? new SingleMatchScorer((Scorer) optionalScorers.get(0))                        : countingDisjunctionSumScorer(optionalScorers, 1))); // require 1 in combined, optional scorer.      }    }  }    /** Returns the scorer to be used for match counting and score summing.   * Uses the given required scorer and the prohibitedScorers.   * @param requiredCountingSumScorer A required scorer already built.   */  private Scorer addProhibitedScorers(Scorer requiredCountingSumScorer)  {    return (prohibitedScorers.size() == 0)          ? requiredCountingSumScorer // no prohibited          : new ReqExclScorer(requiredCountingSumScorer,                              ((prohibitedScorers.size() == 1)                                ? (Scorer) prohibitedScorers.get(0)                                : new DisjunctionSumScorer(prohibitedScorers)));  }  /** 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 {    if (allowDocsOutOfOrder && requiredScorers.size() == 0            && prohibitedScorers.size() < 32) {      // fall back to BooleanScorer, scores documents somewhat out of order      BooleanScorer bs = new BooleanScorer(getSimilarity(), minNrShouldMatch);      Iterator si = optionalScorers.iterator();      while (si.hasNext()) {        bs.add((Scorer) si.next(), false /* required */, false /* prohibited */);      }      si = prohibitedScorers.iterator();      while (si.hasNext()) {        bs.add((Scorer) si.next(), false /* required */, true /* prohibited */);      }      bs.score(hc);    } else {      if (countingSumScorer == null) {        initCountingSumScorer();      }      while (countingSumScorer.next()) {        hc.collect(countingSumScorer.doc(), score());      }    }  }  /** Expert: Collects matching documents in a range.   * <br>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 {    // null pointer exception when next() was not called before:    int docNr = countingSumScorer.doc();    while (docNr < max) {      hc.collect(docNr, score());      if (! countingSumScorer.next()) {        return false;      }      docNr = countingSumScorer.doc();    }    return true;  }  public int doc() { return countingSumScorer.doc(); }  public boolean next() throws IOException {    if (countingSumScorer == null) {      initCountingSumScorer();    }    return countingSumScorer.next();  }  public float score() throws IOException {    coordinator.initDoc();    float sum = countingSumScorer.score();    return sum * coordinator.coordFactor();  }  /** Skips to the first match beyond the current whose document number is   * greater than or equal to a given target.   *    * <p>When this method is used the {@link #explain(int)} method should not be used.   *    * @param target The target document number.   * @return true iff there is such a match.   */  public boolean skipTo(int target) throws IOException {    if (countingSumScorer == null) {      initCountingSumScorer();    }    return countingSumScorer.skipTo(target);  }  /** Throws an UnsupportedOperationException.   * TODO: Implement an explanation of the coordination factor.   * @param doc The document number for the explanation.   * @throws UnsupportedOperationException   */  public Explanation explain(int doc) {    throw new UnsupportedOperationException(); /* How to explain the coordination factor?    initCountingSumScorer();    return countingSumScorer.explain(doc); // misses coord factor.   */  }}

⌨️ 快捷键说明

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