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

« back to all changes in this revision

Viewing changes to solr/core/src/java/org/apache/solr/handler/component/ShardDoc.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
 
/**
2
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 
 * contributor license agreements.  See the NOTICE file distributed with
4
 
 * this work for additional information regarding copyright ownership.
5
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 
 * (the "License"); you may not use this file except in compliance with
7
 
 * the License.  You may obtain a copy of the License at
8
 
 *
9
 
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 
 *
11
 
 * Unless required by applicable law or agreed to in writing, software
12
 
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
 * See the License for the specific language governing permissions and
15
 
 * limitations under the License.
16
 
 */
17
 
package org.apache.solr.handler.component;
18
 
 
19
 
import org.apache.lucene.search.FieldComparatorSource;
20
 
import org.apache.lucene.search.FieldDoc;
21
 
import org.apache.lucene.search.SortField;
22
 
import org.apache.lucene.util.PriorityQueue;
23
 
import org.apache.solr.common.util.NamedList;
24
 
import org.apache.solr.search.MissingStringLastComparatorSource;
25
 
 
26
 
import java.text.Collator;
27
 
import java.util.ArrayList;
28
 
import java.util.Comparator;
29
 
import java.util.List;
30
 
import java.util.Locale;
31
 
 
32
 
public class ShardDoc extends FieldDoc {
33
 
  public String shard;
34
 
  public String shardAddress;  // TODO
35
 
  
36
 
  int orderInShard;
37
 
    // the position of this doc within the shard... this can be used
38
 
    // to short-circuit comparisons if the shard is equal, and can
39
 
    // also be used to break ties within the same shard.
40
 
 
41
 
  public Object id;
42
 
    // this is currently the uniqueKeyField but
43
 
    // may be replaced with internal docid in a future release.
44
 
 
45
 
  Float score;
46
 
 
47
 
  NamedList sortFieldValues;
48
 
  // sort field values for *all* docs in a particular shard.
49
 
  // this doc's values are in position orderInShard
50
 
 
51
 
  // TODO: store the SolrDocument here?
52
 
  // Store the order in the merged list for lookup when getting stored fields?
53
 
  // (other components need this ordering to store data in order, like highlighting)
54
 
  // but we shouldn't expose uniqueKey (have a map by it) until the stored-field
55
 
  // retrieval stage.
56
 
 
57
 
  public int positionInResponse;
58
 
  // the ordinal position in the merged response arraylist  
59
 
 
60
 
  public ShardDoc(float score, Object[] fields, Object uniqueId, String shard) {
61
 
      super(-1, score, fields);
62
 
      this.id = uniqueId;
63
 
      this.shard = shard;
64
 
  }
65
 
 
66
 
  public ShardDoc() {
67
 
    super(-1, Float.NaN);
68
 
  }
69
 
 
70
 
  @Override
71
 
  public boolean equals(Object o) {
72
 
    if (this == o) return true;
73
 
    if (o == null || getClass() != o.getClass()) return false;
74
 
 
75
 
    ShardDoc shardDoc = (ShardDoc) o;
76
 
 
77
 
    if (id != null ? !id.equals(shardDoc.id) : shardDoc.id != null) return false;
78
 
 
79
 
    return true;
80
 
  }
81
 
 
82
 
  @Override
83
 
  public int hashCode() {
84
 
    return id != null ? id.hashCode() : 0;
85
 
  }
86
 
 
87
 
  @Override
88
 
  public String toString(){
89
 
    return "id="+id
90
 
            +" ,score="+score
91
 
            +" ,shard="+shard
92
 
            +" ,orderInShard="+orderInShard
93
 
            +" ,positionInResponse="+positionInResponse
94
 
            +" ,sortFieldValues="+sortFieldValues;
95
 
  }
96
 
}
97
 
 
98
 
 
99
 
 
100
 
// used by distributed search to merge results.
101
 
class ShardFieldSortedHitQueue extends PriorityQueue<ShardDoc> {
102
 
 
103
 
  /** Stores a comparator corresponding to each field being sorted by */
104
 
  protected Comparator[] comparators;
105
 
 
106
 
  /** Stores the sort criteria being used. */
107
 
  protected SortField[] fields;
108
 
 
109
 
  /** The order of these fieldNames should correspond to the order of sort field values retrieved from the shard */
110
 
  protected List<String> fieldNames = new ArrayList<String>();
111
 
 
112
 
  public ShardFieldSortedHitQueue(SortField[] fields, int size) {
113
 
    final int n = fields.length;
114
 
    comparators = new Comparator[n];
115
 
    this.fields = new SortField[n];
116
 
    for (int i = 0; i < n; ++i) {
117
 
 
118
 
      // keep track of the named fields
119
 
      int type = fields[i].getType();
120
 
      if (type!=SortField.SCORE && type!=SortField.DOC) {
121
 
        fieldNames.add(fields[i].getField());
122
 
      }
123
 
 
124
 
      String fieldname = fields[i].getField();
125
 
      comparators[i] = getCachedComparator(fieldname, fields[i]
126
 
          .getType(), fields[i].getLocale(), fields[i].getComparatorSource());
127
 
 
128
 
     if (fields[i].getType() == SortField.STRING) {
129
 
        this.fields[i] = new SortField(fieldname, fields[i].getLocale(),
130
 
            fields[i].getReverse());
131
 
      } else {
132
 
        this.fields[i] = new SortField(fieldname, fields[i].getType(),
133
 
            fields[i].getReverse());
134
 
      }
135
 
 
136
 
      //System.out.println("%%%%%%%%%%%%%%%%%% got "+fields[i].getType() +"   for "+ fieldname +"  fields[i].getReverse(): "+fields[i].getReverse());
137
 
    }
138
 
 
139
 
    initialize(size);
140
 
  }
141
 
 
142
 
  @Override
143
 
  protected boolean lessThan(ShardDoc docA, ShardDoc docB) {
144
 
    // If these docs are from the same shard, then the relative order
145
 
    // is how they appeared in the response from that shard.    
146
 
    if (docA.shard == docB.shard) {
147
 
      // if docA has a smaller position, it should be "larger" so it
148
 
      // comes before docB.
149
 
      // This will handle sorting by docid within the same shard
150
 
 
151
 
      // comment this out to test comparators.
152
 
      return !(docA.orderInShard < docB.orderInShard);
153
 
    }
154
 
 
155
 
 
156
 
    // run comparators
157
 
    final int n = comparators.length;
158
 
    int c = 0;
159
 
    for (int i = 0; i < n && c == 0; i++) {
160
 
      c = (fields[i].getReverse()) ? comparators[i].compare(docB, docA)
161
 
          : comparators[i].compare(docA, docB);
162
 
    }
163
 
 
164
 
    // solve tiebreaks by comparing shards (similar to using docid)
165
 
    // smaller docid's beat larger ids, so reverse the natural ordering
166
 
    if (c == 0) {
167
 
      c = -docA.shard.compareTo(docB.shard);
168
 
    }
169
 
 
170
 
    return c < 0;
171
 
  }
172
 
 
173
 
  Comparator getCachedComparator(String fieldname, int type, Locale locale, FieldComparatorSource factory) {
174
 
    Comparator comparator = null;
175
 
    switch (type) {
176
 
    case SortField.SCORE:
177
 
      comparator = comparatorScore(fieldname);
178
 
      break;
179
 
    case SortField.STRING:
180
 
      if (locale != null)
181
 
        comparator = comparatorStringLocale(fieldname, locale);
182
 
      else
183
 
        comparator = comparatorNatural(fieldname);
184
 
      break;
185
 
    case SortField.CUSTOM:
186
 
      if (factory instanceof MissingStringLastComparatorSource){
187
 
        comparator = comparatorMissingStringLast(fieldname);
188
 
      } else {
189
 
        // TODO: support other types such as random... is there a way to
190
 
        // support generically?  Perhaps just comparing Object
191
 
        comparator = comparatorNatural(fieldname);
192
 
        // throw new RuntimeException("Custom sort not supported factory is "+factory.getClass());
193
 
      }
194
 
      break;
195
 
    case SortField.DOC:
196
 
      // TODO: we can support this!
197
 
      throw new RuntimeException("Doc sort not supported");
198
 
    default:
199
 
      comparator = comparatorNatural(fieldname);
200
 
      break;
201
 
    }
202
 
    return comparator;
203
 
  }
204
 
 
205
 
  class ShardComparator implements Comparator {
206
 
    String fieldName;
207
 
    int fieldNum;
208
 
    public ShardComparator(String fieldName) {
209
 
      this.fieldName = fieldName;
210
 
      this.fieldNum=0;
211
 
      for (int i=0; i<fieldNames.size(); i++) {
212
 
        if (fieldNames.get(i).equals(fieldName)) {
213
 
          this.fieldNum = i;
214
 
          break;
215
 
        }
216
 
      }
217
 
    }
218
 
 
219
 
    Object sortVal(ShardDoc shardDoc) {
220
 
      assert(shardDoc.sortFieldValues.getName(fieldNum).equals(fieldName));
221
 
      List lst = (List)shardDoc.sortFieldValues.getVal(fieldNum);
222
 
      return lst.get(shardDoc.orderInShard);
223
 
    }
224
 
 
225
 
    public int compare(Object o1, Object o2) {
226
 
      return 0;
227
 
    }
228
 
  }
229
 
 
230
 
  static Comparator comparatorScore(final String fieldName) {
231
 
    return new Comparator() {
232
 
      public final int compare(final Object o1, final Object o2) {
233
 
        ShardDoc e1 = (ShardDoc) o1;
234
 
        ShardDoc e2 = (ShardDoc) o2;
235
 
 
236
 
        final float f1 = e1.score;
237
 
        final float f2 = e2.score;
238
 
        if (f1 < f2)
239
 
          return -1;
240
 
        if (f1 > f2)
241
 
          return 1;
242
 
        return 0;
243
 
      }
244
 
    };
245
 
  }
246
 
 
247
 
  // The lucene natural sort ordering corresponds to numeric
248
 
  // and string natural sort orderings (ascending).  Since
249
 
  // the PriorityQueue keeps the biggest elements by default,
250
 
  // we need to reverse the natural compare ordering so that the
251
 
  // smallest elements are kept instead of the largest... hence
252
 
  // the negative sign on the final compareTo().
253
 
  Comparator comparatorNatural(String fieldName) {
254
 
    return new ShardComparator(fieldName) {
255
 
      @Override
256
 
      public final int compare(final Object o1, final Object o2) {
257
 
        ShardDoc sd1 = (ShardDoc) o1;
258
 
        ShardDoc sd2 = (ShardDoc) o2;
259
 
        Comparable v1 = (Comparable)sortVal(sd1);
260
 
        Comparable v2 = (Comparable)sortVal(sd2);
261
 
        if (v1==v2)
262
 
          return 0;
263
 
        if (v1==null)
264
 
          return 1;
265
 
        if(v2==null)
266
 
          return -1;
267
 
        return -v1.compareTo(v2);
268
 
      }
269
 
    };
270
 
  }
271
 
 
272
 
 
273
 
  Comparator comparatorStringLocale(final String fieldName,
274
 
      Locale locale) {
275
 
    final Collator collator = Collator.getInstance(locale);
276
 
    return new ShardComparator(fieldName) {
277
 
      @Override
278
 
      public final int compare(final Object o1, final Object o2) {
279
 
        ShardDoc sd1 = (ShardDoc) o1;
280
 
        ShardDoc sd2 = (ShardDoc) o2;
281
 
        Comparable v1 = (Comparable)sortVal(sd1);
282
 
        Comparable v2 = (Comparable)sortVal(sd2);
283
 
        if (v1==v2)
284
 
          return 0;
285
 
        if (v1==null)
286
 
          return 1;
287
 
        if(v2==null)
288
 
          return -1;
289
 
        return -collator.compare(v1,v2);
290
 
      }
291
 
    };
292
 
  }
293
 
 
294
 
 
295
 
  Comparator comparatorMissingStringLast(final String fieldName) {
296
 
     return new ShardComparator(fieldName) {
297
 
      @Override
298
 
      public final int compare(final Object o1, final Object o2) {
299
 
        ShardDoc sd1 = (ShardDoc) o1;
300
 
        ShardDoc sd2 = (ShardDoc) o2;
301
 
        Comparable v1 = (Comparable)sortVal(sd1);
302
 
        Comparable v2 = (Comparable)sortVal(sd2);
303
 
        if (v1==v2)
304
 
          return 0;
305
 
        if (v1==null)
306
 
          return -1;
307
 
        if(v2==null)
308
 
          return 1;
309
 
        return -v1.compareTo(v2);
310
 
      }
311
 
    };
312
 
  }
313
 
 
314
 
}