pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / src / java / org / apache / lucene / search / function / ValueSourceQuery.java
1 package org.apache.lucene.search.function;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import org.apache.lucene.index.IndexReader;
21 import org.apache.lucene.index.Term;
22 import org.apache.lucene.index.TermDocs;
23 import org.apache.lucene.search.*;
24 import org.apache.lucene.util.ToStringUtils;
25
26 import java.io.IOException;
27 import java.util.Set;
28
29 /**
30  * Expert: A Query that sets the scores of document to the
31  * values obtained from a {@link org.apache.lucene.search.function.ValueSource ValueSource}.
32  * <p>
33  * This query provides a score for <em>each and every</em> undeleted document in the index.    
34  * <p>
35  * The value source can be based on a (cached) value of an indexed field, but it
36  * can also be based on an external source, e.g. values read from an external database. 
37  * <p>
38  * Score is set as: Score(doc,query) = query.getBoost()<sup>2</sup> * valueSource(doc).  
39  *
40  * @lucene.experimental
41  */
42 public class ValueSourceQuery extends Query {
43   ValueSource valSrc;
44
45   /**
46    * Create a value source query
47    * @param valSrc provides the values defines the function to be used for scoring
48    */
49   public ValueSourceQuery(ValueSource valSrc) {
50     this.valSrc=valSrc;
51   }
52
53   /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
54   @Override
55   public Query rewrite(IndexReader reader) throws IOException {
56     return this;
57   }
58
59   /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
60   @Override
61   public void extractTerms(Set<Term> terms) {
62     // no terms involved here
63   }
64
65   class ValueSourceWeight extends Weight {
66     Similarity similarity;
67     float queryNorm;
68     float queryWeight;
69
70     public ValueSourceWeight(Searcher searcher) {
71       this.similarity = getSimilarity(searcher);
72     }
73
74     /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
75     @Override
76     public Query getQuery() {
77       return ValueSourceQuery.this;
78     }
79
80     /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */
81     @Override
82     public float getValue() {
83       return queryWeight;
84     }
85
86     /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */
87     @Override
88     public float sumOfSquaredWeights() throws IOException {
89       queryWeight = getBoost();
90       return queryWeight * queryWeight;
91     }
92
93     /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
94     @Override
95     public void normalize(float norm) {
96       this.queryNorm = norm;
97       queryWeight *= this.queryNorm;
98     }
99
100     @Override
101     public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException {
102       return new ValueSourceScorer(similarity, reader, this);
103     }
104
105     /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */
106     @Override
107     public Explanation explain(IndexReader reader, int doc) throws IOException {
108       DocValues vals = valSrc.getValues(reader);
109       float sc = queryWeight * vals.floatVal(doc);
110
111       Explanation result = new ComplexExplanation(
112         true, sc, ValueSourceQuery.this.toString() + ", product of:");
113
114       result.addDetail(vals.explain(doc));
115       result.addDetail(new Explanation(getBoost(), "boost"));
116       result.addDetail(new Explanation(queryNorm,"queryNorm"));
117       return result;
118     }
119   }
120
121   /**
122    * A scorer that (simply) matches all documents, and scores each document with 
123    * the value of the value source in effect. As an example, if the value source 
124    * is a (cached) field source, then value of that field in that document will 
125    * be used. (assuming field is indexed for this doc, with a single token.)   
126    */
127   private class ValueSourceScorer extends Scorer {
128     private final float qWeight;
129     private final DocValues vals;
130     private final TermDocs termDocs;
131     private int doc = -1;
132
133     // constructor
134     private ValueSourceScorer(Similarity similarity, IndexReader reader, ValueSourceWeight w) throws IOException {
135       super(similarity,w);
136       qWeight = w.getValue();
137       // this is when/where the values are first created.
138       vals = valSrc.getValues(reader);
139       termDocs = reader.termDocs(null);
140     }
141
142     @Override
143     public int nextDoc() throws IOException {
144       return doc = termDocs.next() ? termDocs.doc() : NO_MORE_DOCS;
145     }
146     
147     @Override
148     public int docID() {
149       return doc;
150     }
151     
152     @Override
153     public int advance(int target) throws IOException {
154       return doc = termDocs.skipTo(target) ? termDocs.doc() : NO_MORE_DOCS;
155     }
156     
157     /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
158     @Override
159     public float score() throws IOException {
160       return qWeight * vals.floatVal(termDocs.doc());
161     }
162   }
163
164   @Override
165   public Weight createWeight(Searcher searcher) {
166     return new ValueSourceQuery.ValueSourceWeight(searcher);
167   }
168
169   @Override
170   public String toString(String field) {
171     return valSrc.toString() + ToStringUtils.boost(getBoost());
172   }
173
174   /** Returns true if <code>o</code> is equal to this. */
175   @Override
176   public boolean equals(Object o) {
177     if (this == o)
178       return true;
179     if (!super.equals(o))
180       return false;
181     if (getClass() != o.getClass()) {
182       return false;
183     }
184     ValueSourceQuery other = (ValueSourceQuery)o;
185     return this.getBoost() == other.getBoost()
186            && this.valSrc.equals(other.valSrc);
187   }
188
189   /** Returns a hash code value for this object. */
190   @Override
191   public int hashCode() {
192     return (getClass().hashCode() + valSrc.hashCode()) ^ Float.floatToIntBits(getBoost());
193   }
194
195 }