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

📄 customscorequery.java

📁 lucene2.2.0版本
💻 JAVA
字号:
package org.apache.lucene.search.function;/** * 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.Set;import org.apache.lucene.index.IndexReader;import org.apache.lucene.search.ComplexExplanation;import org.apache.lucene.search.Explanation;import org.apache.lucene.search.Query;import org.apache.lucene.search.Scorer;import org.apache.lucene.search.Searcher;import org.apache.lucene.search.Similarity;import org.apache.lucene.search.Weight;import org.apache.lucene.util.ToStringUtils;/** * Query that sets document score as a programmatic function of (up to) two (sub) scores. * <ol> *    <li>the score of its subQuery (any query)</li> *    <li>(optional) the score of its ValueSourtceQuery, *        for most simple/convineient use case this query would be a  *        {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}</li> * </ol> * Subclasses can modify the computation by overriding {@link #customScore(int, float, float)}. *  * <p><font color="#FF0000"> * WARNING: The status of the <b>search.function</b> package is experimental.  * The APIs introduced here might change in the future and will not be  * supported anymore in such a case.</font> */public class CustomScoreQuery extends Query {  private Query subQuery;  private ValueSourceQuery valSrcQuery; // optional, can be null  private boolean strict = false; // if true, valueSource part of query does not take part in weights normalization.      /**   * Create a CustomScoreQuery over input subQuery.   * @param subQuery the sub query whose scored is being customed. Must not be null.    */  public CustomScoreQuery(Query subQuery) {    this(subQuery,null);  }  /**   * Create a CustomScoreQuery over input subQuery and a {@link ValueSourceQuery}.   * @param subQuery the sub query whose score is being customed. Must not be null.   * @param valSrcQuery a value source query whose scores are used in the custom score   * computation. For most simple/convineient use case this would be a    * {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}.   * This parameter is optional - it can be null.   */  public CustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {    super();    this.subQuery = subQuery;    this.valSrcQuery = valSrcQuery;    if (subQuery == null) throw new IllegalArgumentException("<subqyery> must not be null!");  }  /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */  public Query rewrite(IndexReader reader) throws IOException {    subQuery = subQuery.rewrite(reader);    if (valSrcQuery!=null) {      valSrcQuery = (ValueSourceQuery) valSrcQuery.rewrite(reader);    }    return this;  }  /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */  public void extractTerms(Set terms) {    subQuery.extractTerms(terms);    if (valSrcQuery!=null) {      valSrcQuery.extractTerms(terms);    }  }  /*(non-Javadoc) @see org.apache.lucene.search.Query#clone() */  public Object clone() {    CustomScoreQuery clone = (CustomScoreQuery)super.clone();    clone.subQuery = (Query) subQuery.clone();    if (valSrcQuery!=null) {      clone.valSrcQuery = (ValueSourceQuery) valSrcQuery.clone();    }    return clone;  }  /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */  public String toString(String field) {    StringBuffer sb = new StringBuffer(name()).append("(");    sb.append(subQuery.toString(field));    if (valSrcQuery!=null) {      sb.append(", ").append(valSrcQuery.toString(field));    }    sb.append(")");    sb.append(strict?" STRICT" : "");    return sb.toString() + ToStringUtils.boost(getBoost());  }  /** Returns true if <code>o</code> is equal to this. */  public boolean equals(Object o) {    if (getClass() != o.getClass()) {      return false;    }    CustomScoreQuery other = (CustomScoreQuery)o;    return this.getBoost() == other.getBoost()           && this.subQuery.equals(other.subQuery)           && (this.valSrcQuery==null ? other.valSrcQuery==null                : this.valSrcQuery.equals(other.valSrcQuery));  }  /** Returns a hash code value for this object. */  public int hashCode() {    int valSrcHash = valSrcQuery==null ? 0 : valSrcQuery.hashCode();    return (getClass().hashCode() + subQuery.hashCode() + valSrcHash) ^ Float.floatToIntBits(getBoost());  }      /**   * Compute a custom score by the subQuery score and the ValueSourceQuery score.   * <p>    * Subclasses can override this method to modify the custom score.   * <p>   * The default computation herein is:   * <pre>   *     ModifiedScore = valSrcScore * subQueryScore.   * </pre>   *    * @param doc id of scored doc.    * @param subQueryScore score of that doc by the subQuery.   * @param valSrcScore score of that doc by the ValueSourceQuery.   * @return custom score.   */  public float customScore(int doc, float subQueryScore, float valSrcScore) {    return valSrcScore * subQueryScore;  }  /**   * Explain the custom score.   * Whenever overriding {@link #customScore(int, float, float)},    * this method should also be overriden to provide the correct explanation   * for the part of the custom scoring.    * @param doc doc being explained.   * @param subQueryExpl explanation for the sub-query part.   * @param valSrcExpl explanation for the value source part.   * @return an explanation for the custom score   */  public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {    float valSrcScore = valSrcExpl==null ? 1 : valSrcExpl.getValue();    Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");    exp.addDetail(subQueryExpl);    if (valSrcExpl != null) {      exp.addDetail(valSrcExpl);    }    return exp;  }  //=========================== W E I G H T ============================    private class CustomWeight implements Weight {    Searcher searcher;    Weight subQueryWeight;    Weight valSrcWeight; // optional    boolean qStrict;    public CustomWeight(Searcher searcher) throws IOException {      this.searcher = searcher;      this.subQueryWeight = subQuery.weight(searcher);       if (valSrcQuery!=null) {        this.valSrcWeight = valSrcQuery.createWeight(searcher);      }      this.qStrict = strict;    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */    public Query getQuery() {      return CustomScoreQuery.this;    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */    public float getValue() {      return getBoost();    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */    public float sumOfSquaredWeights() throws IOException {      float sum = subQueryWeight.sumOfSquaredWeights();      if (valSrcWeight!=null) {        if (qStrict) {          valSrcWeight.sumOfSquaredWeights(); // do not include ValueSource part in the query normalization        } else {          sum += valSrcWeight.sumOfSquaredWeights();        }      }      sum *= getBoost() * getBoost(); // boost each sub-weight      return sum ;    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */    public void normalize(float norm) {      norm *= getBoost(); // incorporate boost      subQueryWeight.normalize(norm);      if (valSrcWeight!=null) {        if (qStrict) {          valSrcWeight.normalize(1); // do not normalize the ValueSource part        } else {          valSrcWeight.normalize(norm);        }      }    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */    public Scorer scorer(IndexReader reader) throws IOException {      Scorer subQueryScorer = subQueryWeight.scorer(reader);      Scorer valSrcScorer = (valSrcWeight==null ? null : valSrcWeight.scorer(reader));      return new CustomScorer(getSimilarity(searcher), reader, this, subQueryScorer, valSrcScorer);    }    /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */    public Explanation explain(IndexReader reader, int doc) throws IOException {      return scorer(reader).explain(doc);    }  }  //=========================== S C O R E R ============================    /**   * A scorer that applies a (callback) function on scores of the subQuery.   */  private class CustomScorer extends Scorer {    private final CustomWeight weight;    private final float qWeight;    private Scorer subQueryScorer;    private Scorer valSrcScorer; // optional    private IndexReader reader;    // constructor    private CustomScorer(Similarity similarity, IndexReader reader, CustomWeight w,        Scorer subQueryScorer, Scorer valSrcScorer) throws IOException {      super(similarity);      this.weight = w;      this.qWeight = w.getValue();      this.subQueryScorer = subQueryScorer;      this.valSrcScorer = valSrcScorer;      this.reader = reader;    }    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */    public boolean next() throws IOException {      boolean hasNext = subQueryScorer.next();      if (valSrcScorer!=null && hasNext) {        valSrcScorer.skipTo(subQueryScorer.doc());      }      return hasNext;    }    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() */    public int doc() {      return subQueryScorer.doc();    }    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */    public float score() throws IOException {      float valSrcScore = (valSrcScorer==null ? 1 : valSrcScorer.score());      return qWeight * customScore(subQueryScorer.doc(), subQueryScorer.score(), valSrcScore);    }    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */    public boolean skipTo(int target) throws IOException {      boolean hasNext = subQueryScorer.skipTo(target);      if (valSrcScorer!=null && hasNext) {        valSrcScorer.skipTo(subQueryScorer.doc());      }      return hasNext;    }    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */    public Explanation explain(int doc) throws IOException {      Explanation subQueryExpl = weight.subQueryWeight.explain(reader,doc);      if (!subQueryExpl.isMatch()) {        return subQueryExpl;      }      // match      Explanation valSrcExpl = valSrcScorer==null ? null : valSrcScorer.explain(doc);      Explanation customExp = customExplain(doc,subQueryExpl,valSrcExpl);      float sc = qWeight * customExp.getValue();      Explanation res = new ComplexExplanation(        true, sc, CustomScoreQuery.this.toString() + ", product of:");      res.addDetail(customExp);      res.addDetail(new Explanation(qWeight, "queryBoost")); // actually using the q boost as q weight (== weight value)      return res;    }  }  /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */  protected Weight createWeight(Searcher searcher) throws IOException {    return new CustomWeight(searcher);  }  /**   * Checks if this is strict custom scoring.   * In strict custom scoring, the ValueSource part of does not participate in weight normalization.   * This may be useful when one wants full control over how scores are modified, and does    * not care about normalizing by the ValueSource part.   * One particular case where this is useful if for testing this query.      * <P>   * Note: only has effect when the ValueSource part is not null.   */  public boolean isStrict() {    return strict;  }  /**   * Set the strict mode of this query.    * @param strict The strict mode to set.   * @see #isStrict()   */  public void setStrict(boolean strict) {    this.strict = strict;  }  /**   * A short name of this query, used in {@link #toString(String)}.   */  public String name() {    return "custom";  }}

⌨️ 快捷键说明

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