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

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/search/ConjunctionScorer.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.util.ArrayUtil;
21
 
import java.io.IOException;
22
 
import java.util.Collection;
23
 
import java.util.Comparator;
24
 
 
25
 
/** Scorer for conjunctions, sets of queries, all of which are required. */
26
 
class ConjunctionScorer extends Scorer {
27
 
  
28
 
  private final Scorer[] scorers;
29
 
  private final float coord;
30
 
  private int lastDoc = -1;
31
 
 
32
 
  public ConjunctionScorer(Weight weight, float coord, Collection<Scorer> scorers) throws IOException {
33
 
    this(weight, coord, scorers.toArray(new Scorer[scorers.size()]));
34
 
  }
35
 
 
36
 
  public ConjunctionScorer(Weight weight, float coord, Scorer... scorers) throws IOException {
37
 
    super(weight);
38
 
    this.scorers = scorers;
39
 
    this.coord = coord;
40
 
    
41
 
    for (int i = 0; i < scorers.length; i++) {
42
 
      if (scorers[i].nextDoc() == NO_MORE_DOCS) {
43
 
        // If even one of the sub-scorers does not have any documents, this
44
 
        // scorer should not attempt to do any more work.
45
 
        lastDoc = NO_MORE_DOCS;
46
 
        return;
47
 
      }
48
 
    }
49
 
 
50
 
    // Sort the array the first time...
51
 
    // We don't need to sort the array in any future calls because we know
52
 
    // it will already start off sorted (all scorers on same doc).
53
 
    
54
 
    // Note that this comparator is not consistent with equals!
55
 
    // Also we use mergeSort here to be stable (so order of Scoreres that
56
 
    // match on first document keeps preserved):
57
 
    ArrayUtil.mergeSort(scorers, new Comparator<Scorer>() { // sort the array
58
 
      public int compare(Scorer o1, Scorer o2) {
59
 
        return o1.docID() - o2.docID();
60
 
      }
61
 
    });
62
 
 
63
 
    // NOTE: doNext() must be called before the re-sorting of the array later on.
64
 
    // The reason is this: assume there are 5 scorers, whose first docs are 1,
65
 
    // 2, 3, 5, 5 respectively. Sorting (above) leaves the array as is. Calling
66
 
    // doNext() here advances all the first scorers to 5 (or a larger doc ID
67
 
    // they all agree on). 
68
 
    // However, if we re-sort before doNext() is called, the order will be 5, 3,
69
 
    // 2, 1, 5 and then doNext() will stop immediately, since the first scorer's
70
 
    // docs equals the last one. So the invariant that after calling doNext() 
71
 
    // all scorers are on the same doc ID is broken.
72
 
    if (doNext() == NO_MORE_DOCS) {
73
 
      // The scorers did not agree on any document.
74
 
      lastDoc = NO_MORE_DOCS;
75
 
      return;
76
 
    }
77
 
 
78
 
    // If first-time skip distance is any predictor of
79
 
    // scorer sparseness, then we should always try to skip first on
80
 
    // those scorers.
81
 
    // Keep last scorer in it's last place (it will be the first
82
 
    // to be skipped on), but reverse all of the others so that
83
 
    // they will be skipped on in order of original high skip.
84
 
    int end = scorers.length - 1;
85
 
    int max = end >> 1;
86
 
    for (int i = 0; i < max; i++) {
87
 
      Scorer tmp = scorers[i];
88
 
      int idx = end - i - 1;
89
 
      scorers[i] = scorers[idx];
90
 
      scorers[idx] = tmp;
91
 
    }
92
 
  }
93
 
 
94
 
  private int doNext() throws IOException {
95
 
    int first = 0;
96
 
    int doc = scorers[scorers.length - 1].docID();
97
 
    Scorer firstScorer;
98
 
    while ((firstScorer = scorers[first]).docID() < doc) {
99
 
      doc = firstScorer.advance(doc);
100
 
      first = first == scorers.length - 1 ? 0 : first + 1;
101
 
    }
102
 
    return doc;
103
 
  }
104
 
  
105
 
  @Override
106
 
  public int advance(int target) throws IOException {
107
 
    if (lastDoc == NO_MORE_DOCS) {
108
 
      return lastDoc;
109
 
    } else if (scorers[(scorers.length - 1)].docID() < target) {
110
 
      scorers[(scorers.length - 1)].advance(target);
111
 
    }
112
 
    return lastDoc = doNext();
113
 
  }
114
 
 
115
 
  @Override
116
 
  public int docID() {
117
 
    return lastDoc;
118
 
  }
119
 
  
120
 
  @Override
121
 
  public int nextDoc() throws IOException {
122
 
    if (lastDoc == NO_MORE_DOCS) {
123
 
      return lastDoc;
124
 
    } else if (lastDoc == -1) {
125
 
      return lastDoc = scorers[scorers.length - 1].docID();
126
 
    }
127
 
    scorers[(scorers.length - 1)].nextDoc();
128
 
    return lastDoc = doNext();
129
 
  }
130
 
  
131
 
  @Override
132
 
  public float score() throws IOException {
133
 
    float sum = 0.0f;
134
 
    for (int i = 0; i < scorers.length; i++) {
135
 
      sum += scorers[i].score();
136
 
    }
137
 
    return sum * coord;
138
 
  }
139
 
}