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

« back to all changes in this revision

Viewing changes to solr/core/src/java/org/apache/solr/schema/RandomSortField.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
 
 
18
 
package org.apache.solr.schema;
19
 
 
20
 
import java.io.IOException;
21
 
import java.util.Map;
22
 
 
23
 
import org.apache.lucene.document.Fieldable;
24
 
import org.apache.lucene.index.IndexReader;
25
 
import org.apache.lucene.search.*;
26
 
import org.apache.solr.response.TextResponseWriter;
27
 
import org.apache.solr.response.XMLWriter;
28
 
import org.apache.solr.search.QParser;
29
 
import org.apache.solr.search.function.DocValues;
30
 
import org.apache.solr.search.function.ValueSource;
31
 
import org.apache.solr.search.SolrIndexReader;
32
 
 
33
 
/**
34
 
 * Utility Field used for random sorting.  It should not be passed a value.
35
 
 * <p>
36
 
 * This random sorting implementation uses the dynamic field name to set the
37
 
 * random 'seed'.  To get random sorting order, you need to use a random
38
 
 * dynamic field name.  For example, you will need to configure schema.xml:
39
 
 * <pre>
40
 
 * &lt;types&gt;
41
 
 *  ...
42
 
 *  &lt;fieldType name="random" class="solr.RandomSortField" /&gt;
43
 
 *  ... 
44
 
 * &lt;/types&gt;
45
 
 * &lt;fields&gt;
46
 
 *  ...
47
 
 *  &lt;dynamicField name="random*" type="random" indexed="true" stored="false"/&gt;
48
 
 *  ...
49
 
 * &lt;/fields&gt;
50
 
 * </pre>
51
 
 * 
52
 
 * Examples of queries:
53
 
 * <ul>
54
 
 * <li>http://localhost:8983/solr/select/?q=*:*&fl=name&sort=rand_1234%20desc</li>
55
 
 * <li>http://localhost:8983/solr/select/?q=*:*&fl=name&sort=rand_2345%20desc</li>
56
 
 * <li>http://localhost:8983/solr/select/?q=*:*&fl=name&sort=rand_ABDC%20desc</li>
57
 
 * <li>http://localhost:8983/solr/select/?q=*:*&fl=name&sort=rand_21%20desc</li>
58
 
 * </ul>
59
 
 * Note that multiple calls to the same URL will return the same sorting order.
60
 
 * 
61
 
 * @version $Id: RandomSortField.java 1136465 2011-06-16 14:50:22Z mikemccand $
62
 
 * @since solr 1.3
63
 
 */
64
 
public class RandomSortField extends FieldType {
65
 
  // Thomas Wang's hash32shift function, from http://www.cris.com/~Ttwang/tech/inthash.htm
66
 
  // slightly modified to return only positive integers.
67
 
  private static int hash(int key) {
68
 
    key = ~key + (key << 15); // key = (key << 15) - key - 1;
69
 
    key = key ^ (key >>> 12);
70
 
    key = key + (key << 2);
71
 
    key = key ^ (key >>> 4);
72
 
    key = key * 2057; // key = (key + (key << 3)) + (key << 11);
73
 
    key = key ^ (key >>> 16);
74
 
    return key >>> 1; 
75
 
  }
76
 
 
77
 
  /** 
78
 
   * Given a field name and an IndexReader, get a random hash seed.  
79
 
   * Using dynamic fields, you can force the random order to change 
80
 
   */
81
 
  private static int getSeed(String fieldName, IndexReader r) {
82
 
    SolrIndexReader top = (SolrIndexReader)r;
83
 
    int base=0;
84
 
    while (top.getParent() != null) {
85
 
      base += top.getBase();
86
 
      top = top.getParent();
87
 
    }
88
 
 
89
 
    // calling getVersion() on a segment will currently give you a null pointer exception, so
90
 
    // we use the top-level reader.
91
 
    return fieldName.hashCode() + base + (int)top.getVersion();
92
 
  }
93
 
 
94
 
  @Override
95
 
  public SortField getSortField(SchemaField field, boolean reverse) {
96
 
    return new SortField(field.getName(), randomComparatorSource, reverse);
97
 
  }
98
 
 
99
 
  @Override
100
 
  public ValueSource getValueSource(SchemaField field, QParser parser) {
101
 
    return new RandomValueSource(field.getName());
102
 
  }
103
 
 
104
 
  @Override
105
 
  public void write(XMLWriter xmlWriter, String name, Fieldable f) throws IOException { }
106
 
 
107
 
  @Override
108
 
  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException { }
109
 
 
110
 
 
111
 
  private static FieldComparatorSource randomComparatorSource = new FieldComparatorSource() {
112
 
    @Override
113
 
    public FieldComparator<Integer> newComparator(final String fieldname, final int numHits, int sortPos, boolean reversed) throws IOException {
114
 
      return new FieldComparator<Integer>() {
115
 
        int seed;
116
 
        private final int[] values = new int[numHits];
117
 
        int bottomVal;
118
 
 
119
 
        @Override
120
 
        public int compare(int slot1, int slot2) {
121
 
          return values[slot1] - values[slot2];  // values will be positive... no overflow possible.
122
 
        }
123
 
 
124
 
        @Override
125
 
        public void setBottom(int slot) {
126
 
          bottomVal = values[slot];
127
 
        }
128
 
 
129
 
        @Override
130
 
        public int compareBottom(int doc) throws IOException {
131
 
          return bottomVal - hash(doc+seed);
132
 
        }
133
 
 
134
 
        @Override
135
 
        public void copy(int slot, int doc) throws IOException {
136
 
          values[slot] = hash(doc+seed);
137
 
        }
138
 
 
139
 
        @Override
140
 
        public void setNextReader(IndexReader reader, int docBase) throws IOException {
141
 
          seed = getSeed(fieldname, reader);
142
 
        }
143
 
 
144
 
        @Override
145
 
        public Integer value(int slot) {
146
 
          return values[slot];
147
 
        }
148
 
      };
149
 
    }
150
 
  };
151
 
 
152
 
 
153
 
 
154
 
  public class RandomValueSource extends ValueSource {
155
 
    private final String field;
156
 
 
157
 
    public RandomValueSource(String field) {
158
 
      this.field=field;
159
 
    }
160
 
 
161
 
    @Override
162
 
    public String description() {
163
 
      return field;
164
 
    }
165
 
 
166
 
    @Override
167
 
    public DocValues getValues(Map context, final IndexReader reader) throws IOException {
168
 
      return new DocValues() {
169
 
          private final int seed = getSeed(field, reader);
170
 
          @Override
171
 
          public float floatVal(int doc) {
172
 
            return (float)hash(doc+seed);
173
 
          }
174
 
 
175
 
          @Override
176
 
          public int intVal(int doc) {
177
 
            return hash(doc+seed);
178
 
          }
179
 
 
180
 
          @Override
181
 
          public long longVal(int doc) {
182
 
            return (long)hash(doc+seed);
183
 
          }
184
 
 
185
 
          @Override
186
 
          public double doubleVal(int doc) {
187
 
            return (double)hash(doc+seed);
188
 
          }
189
 
 
190
 
          @Override
191
 
          public String strVal(int doc) {
192
 
            return Integer.toString(hash(doc+seed));
193
 
          }
194
 
 
195
 
          @Override
196
 
          public String toString(int doc) {
197
 
            return description() + '=' + intVal(doc);
198
 
          }
199
 
        };
200
 
    }
201
 
 
202
 
    @Override
203
 
    public boolean equals(Object o) {
204
 
      if (!(o instanceof RandomValueSource)) return false;
205
 
      RandomValueSource other = (RandomValueSource)o;
206
 
      return this.field.equals(other.field);
207
 
    }
208
 
 
209
 
    @Override
210
 
    public int hashCode() {
211
 
      return field.hashCode();
212
 
    };
213
 
  }
214
 
}
215
 
 
216
 
 
217
 
 
218
 
 
219