~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/search/ConstantScoreQuery.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.apache.lucene.search;
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.util.ToStringUtils;
23
 
 
24
 
import java.io.IOException;
25
 
import java.util.Set;
26
 
 
27
 
/**
28
 
 * A query that wraps another query or a filter and simply returns a constant score equal to the
29
 
 * query boost for every document that matches the filter or query.
30
 
 * For queries it therefore simply strips of all scores and returns a constant one.
31
 
 *
32
 
 * <p><b>NOTE</b>: if the wrapped filter is an instance of
33
 
 * {@link CachingWrapperFilter}, you'll likely want to
34
 
 * enforce deletions in the filter (using either {@link
35
 
 * CachingWrapperFilter.DeletesMode#RECACHE} or {@link
36
 
 * CachingWrapperFilter.DeletesMode#DYNAMIC}).
37
 
 */
38
 
public class ConstantScoreQuery extends Query {
39
 
  protected final Filter filter;
40
 
  protected final Query query;
41
 
 
42
 
  /** Strips off scores from the passed in Query. The hits will get a constant score
43
 
   * dependent on the boost factor of this query. */
44
 
  public ConstantScoreQuery(Query query) {
45
 
    if (query == null)
46
 
      throw new NullPointerException("Query may not be null");
47
 
    this.filter = null;
48
 
    this.query = query;
49
 
  }
50
 
 
51
 
  /** Wraps a Filter as a Query. The hits will get a constant score
52
 
   * dependent on the boost factor of this query.
53
 
   * If you simply want to strip off scores from a Query, no longer use
54
 
   * {@code new ConstantScoreQuery(new QueryWrapperFilter(query))}, instead
55
 
   * use {@link #ConstantScoreQuery(Query)}!
56
 
   */
57
 
  public ConstantScoreQuery(Filter filter) {
58
 
    if (filter == null)
59
 
      throw new NullPointerException("Filter may not be null");
60
 
    this.filter = filter;
61
 
    this.query = null;
62
 
  }
63
 
 
64
 
  /** Returns the encapsulated filter, returns {@code null} if a query is wrapped. */
65
 
  public Filter getFilter() {
66
 
    return filter;
67
 
  }
68
 
 
69
 
  /** Returns the encapsulated query, returns {@code null} if a filter is wrapped. */
70
 
  public Query getQuery() {
71
 
    return query;
72
 
  }
73
 
 
74
 
  @Override
75
 
  public Query rewrite(IndexReader reader) throws IOException {
76
 
    if (query != null) {
77
 
      Query rewritten = query.rewrite(reader);
78
 
      if (rewritten != query) {
79
 
        rewritten = new ConstantScoreQuery(rewritten);
80
 
        rewritten.setBoost(this.getBoost());
81
 
        return rewritten;
82
 
      }
83
 
    }
84
 
    return this;
85
 
  }
86
 
 
87
 
  @Override
88
 
  public void extractTerms(Set<Term> terms) {
89
 
    // TODO: OK to not add any terms when wrapped a filter
90
 
    // and used with MultiSearcher, but may not be OK for
91
 
    // highlighting.
92
 
    // If a query was wrapped, we delegate to query.
93
 
    if (query != null)
94
 
      query.extractTerms(terms);
95
 
  }
96
 
 
97
 
  protected class ConstantWeight extends Weight {
98
 
    private final Weight innerWeight;
99
 
    private final Similarity similarity;
100
 
    private float queryNorm;
101
 
    private float queryWeight;
102
 
    
103
 
    public ConstantWeight(Searcher searcher) throws IOException {
104
 
      this.similarity = getSimilarity(searcher);
105
 
      this.innerWeight = (query == null) ? null : query.createWeight(searcher);
106
 
    }
107
 
 
108
 
    @Override
109
 
    public Query getQuery() {
110
 
      return ConstantScoreQuery.this;
111
 
    }
112
 
 
113
 
    @Override
114
 
    public float getValue() {
115
 
      return queryWeight;
116
 
    }
117
 
 
118
 
    @Override
119
 
    public float sumOfSquaredWeights() throws IOException {
120
 
      // we calculate sumOfSquaredWeights of the inner weight, but ignore it (just to initialize everything)
121
 
      if (innerWeight != null) innerWeight.sumOfSquaredWeights();
122
 
      queryWeight = getBoost();
123
 
      return queryWeight * queryWeight;
124
 
    }
125
 
 
126
 
    @Override
127
 
    public void normalize(float norm) {
128
 
      this.queryNorm = norm;
129
 
      queryWeight *= this.queryNorm;
130
 
      // we normalize the inner weight, but ignore it (just to initialize everything)
131
 
      if (innerWeight != null) innerWeight.normalize(norm);
132
 
    }
133
 
 
134
 
    @Override
135
 
    public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException {
136
 
      final DocIdSetIterator disi;
137
 
      if (filter != null) {
138
 
        assert query == null;
139
 
        final DocIdSet dis = filter.getDocIdSet(reader);
140
 
        if (dis == null)
141
 
          return null;
142
 
        disi = dis.iterator();
143
 
      } else {
144
 
        assert query != null && innerWeight != null;
145
 
        disi =
146
 
          innerWeight.scorer(reader, scoreDocsInOrder, topScorer);
147
 
      }
148
 
      if (disi == null)
149
 
        return null;
150
 
      return new ConstantScorer(similarity, disi, this);
151
 
    }
152
 
    
153
 
    @Override
154
 
    public boolean scoresDocsOutOfOrder() {
155
 
      return (innerWeight != null) ? innerWeight.scoresDocsOutOfOrder() : false;
156
 
    }
157
 
 
158
 
    @Override
159
 
    public Explanation explain(IndexReader reader, int doc) throws IOException {
160
 
      final Scorer cs = scorer(reader, true, false);
161
 
      final boolean exists = (cs != null && cs.advance(doc) == doc);
162
 
 
163
 
      final ComplexExplanation result = new ComplexExplanation();
164
 
      if (exists) {
165
 
        result.setDescription(ConstantScoreQuery.this.toString() + ", product of:");
166
 
        result.setValue(queryWeight);
167
 
        result.setMatch(Boolean.TRUE);
168
 
        result.addDetail(new Explanation(getBoost(), "boost"));
169
 
        result.addDetail(new Explanation(queryNorm, "queryNorm"));
170
 
      } else {
171
 
        result.setDescription(ConstantScoreQuery.this.toString() + " doesn't match id " + doc);
172
 
        result.setValue(0);
173
 
        result.setMatch(Boolean.FALSE);
174
 
      }
175
 
      return result;
176
 
    }
177
 
  }
178
 
 
179
 
  protected class ConstantScorer extends Scorer {
180
 
    final DocIdSetIterator docIdSetIterator;
181
 
    final float theScore;
182
 
 
183
 
    public ConstantScorer(Similarity similarity, DocIdSetIterator docIdSetIterator, Weight w) throws IOException {
184
 
      super(similarity,w);
185
 
      theScore = w.getValue();
186
 
      this.docIdSetIterator = docIdSetIterator;
187
 
    }
188
 
 
189
 
    @Override
190
 
    public int nextDoc() throws IOException {
191
 
      return docIdSetIterator.nextDoc();
192
 
    }
193
 
    
194
 
    @Override
195
 
    public int docID() {
196
 
      return docIdSetIterator.docID();
197
 
    }
198
 
 
199
 
    @Override
200
 
    public float score() throws IOException {
201
 
      return theScore;
202
 
    }
203
 
 
204
 
    @Override
205
 
    public int advance(int target) throws IOException {
206
 
      return docIdSetIterator.advance(target);
207
 
    }
208
 
    
209
 
    private Collector wrapCollector(final Collector collector) {
210
 
      return new Collector() {
211
 
        @Override
212
 
        public void setScorer(Scorer scorer) throws IOException {
213
 
          // we must wrap again here, but using the scorer passed in as parameter:
214
 
          collector.setScorer(new ConstantScorer(ConstantScorer.this.getSimilarity(),
215
 
            scorer, ConstantScorer.this.weight));
216
 
        }
217
 
        
218
 
        @Override
219
 
        public void collect(int doc) throws IOException {
220
 
          collector.collect(doc);
221
 
        }
222
 
        
223
 
        @Override
224
 
        public void setNextReader(IndexReader reader, int docBase) throws IOException {
225
 
          collector.setNextReader(reader, docBase);
226
 
        }
227
 
        
228
 
        @Override
229
 
        public boolean acceptsDocsOutOfOrder() {
230
 
          return collector.acceptsDocsOutOfOrder();
231
 
        }
232
 
      };
233
 
    }
234
 
 
235
 
    // this optimization allows out of order scoring as top scorer!
236
 
    @Override
237
 
    public void score(Collector collector) throws IOException {
238
 
      if (docIdSetIterator instanceof Scorer) {
239
 
        ((Scorer) docIdSetIterator).score(wrapCollector(collector));
240
 
      } else {
241
 
        super.score(collector);
242
 
      }
243
 
    }
244
 
 
245
 
    // this optimization allows out of order scoring as top scorer,
246
 
    // TODO: theoretically this method should not be called because its protected and
247
 
    // this class does not use it, it should be public in Scorer!
248
 
    @Override
249
 
    protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
250
 
      if (docIdSetIterator instanceof Scorer) {
251
 
        return ((Scorer) docIdSetIterator).score(wrapCollector(collector), max, firstDocID);
252
 
      } else {
253
 
        return super.score(collector, max, firstDocID);
254
 
      }
255
 
    }
256
 
  }
257
 
 
258
 
  @Override
259
 
  public Weight createWeight(Searcher searcher) throws IOException {
260
 
    return new ConstantScoreQuery.ConstantWeight(searcher);
261
 
  }
262
 
 
263
 
  @Override
264
 
  public String toString(String field) {
265
 
    return new StringBuilder("ConstantScore(")
266
 
      .append((query == null) ? filter.toString() : query.toString(field))
267
 
      .append(')')
268
 
      .append(ToStringUtils.boost(getBoost()))
269
 
      .toString();
270
 
  }
271
 
 
272
 
  @Override
273
 
  public boolean equals(Object o) {
274
 
    if (this == o) return true;
275
 
    if (!super.equals(o))
276
 
      return false;
277
 
    if (o instanceof ConstantScoreQuery) {
278
 
      final ConstantScoreQuery other = (ConstantScoreQuery) o;
279
 
      return 
280
 
        ((this.filter == null) ? other.filter == null : this.filter.equals(other.filter)) &&
281
 
        ((this.query == null) ? other.query == null : this.query.equals(other.query));
282
 
    }
283
 
    return false;
284
 
  }
285
 
 
286
 
  @Override
287
 
  public int hashCode() {
288
 
    return 31 * super.hashCode() +
289
 
      ((query == null) ? filter : query).hashCode();
290
 
  }
291
 
 
292
 
}