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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.solr.search;
20
import org.apache.solr.common.SolrException;
21
import org.apache.lucene.util.OpenBitSet;
22
import org.apache.lucene.search.DocIdSet;
23
import org.apache.lucene.search.Filter;
24
import org.apache.lucene.search.DocIdSetIterator;
25
import org.apache.lucene.index.IndexReader;
27
import java.io.IOException;
30
* <code>DocSet</code> represents an unordered set of Lucene Document Ids.
33
* WARNING: Any DocSet returned from SolrIndexSearcher should <b>not</b> be modified as it may have been retrieved from
34
* a cache and could be shared.
37
* @version $Id: DocSet.java 1065312 2011-01-30 16:08:25Z rmuir $
40
public interface DocSet /* extends Collection<Integer> */ {
43
* Adds the specified document if it is not currently in the DocSet
44
* (optional operation).
47
* @throws SolrException if the implementation does not allow modifications
49
public void add(int doc);
52
* Adds a document the caller knows is not currently in the DocSet
53
* (optional operation).
56
* This method may be faster then <code>add(doc)</code> in some
57
* implementaions provided the caller is certain of the precondition.
61
* @throws SolrException if the implementation does not allow modifications
63
public void addUnique(int doc);
66
* Returns the number of documents in the set.
71
* Returns true if a document is in the DocSet.
73
public boolean exists(int docid);
76
* Returns an iterator that may be used to iterate over all of the documents in the set.
79
* The order of the documents returned by this iterator is
80
* non-deterministic, and any scoring information is meaningless
83
public DocIterator iterator();
86
* Returns a BitSet view of the DocSet. Any changes to this BitSet <b>may</b>
87
* be reflected in the DocSet, hence if the DocSet is shared or was returned from
88
* a SolrIndexSearcher method, it's not safe to modify the BitSet.
91
* An OpenBitSet with the bit number of every docid set in the set.
93
* @deprecated Use {@link #iterator()} to access all docs instead.
96
public OpenBitSet getBits();
99
* Returns the approximate amount of memory taken by this DocSet.
100
* This is only an approximation and doesn't take into account java object overhead.
103
* the approximate memory consumption in bytes
105
public long memSize();
108
* Returns the intersection of this set with another set. Neither set is modified - a new DocSet is
109
* created and returned.
110
* @return a DocSet representing the intersection
112
public DocSet intersection(DocSet other);
115
* Returns the number of documents of the intersection of this set with another set.
116
* May be more efficient than actually creating the intersection and then getting it's size.
118
public int intersectionSize(DocSet other);
121
* Returns the union of this set with another set. Neither set is modified - a new DocSet is
122
* created and returned.
123
* @return a DocSet representing the union
125
public DocSet union(DocSet other);
128
* Returns the number of documents of the union of this set with another set.
129
* May be more efficient than actually creating the union and then getting it's size.
131
public int unionSize(DocSet other);
134
* Returns the documents in this set that are not in the other set. Neither set is modified - a new DocSet is
135
* created and returned.
136
* @return a DocSet representing this AND NOT other
138
public DocSet andNot(DocSet other);
141
* Returns the number of documents in this set that are not in the other set.
143
public int andNotSize(DocSet other);
146
* Returns a Filter for use in Lucene search methods, assuming this DocSet
147
* was generated from the top-level MultiReader that the Lucene search
148
* methods will be invoked with.
150
public Filter getTopFilter();
153
/** A base class that may be usefull for implementing DocSets */
154
abstract class DocSetBase implements DocSet {
156
// Not implemented efficiently... for testing purposes only
158
public boolean equals(Object obj) {
159
if (!(obj instanceof DocSet)) return false;
160
DocSet other = (DocSet)obj;
161
if (this.size() != other.size()) return false;
163
if (this instanceof DocList && other instanceof DocList) {
165
DocIterator i1=this.iterator();
166
DocIterator i2=other.iterator();
167
while(i1.hasNext() && i2.hasNext()) {
168
if (i1.nextDoc() != i2.nextDoc()) return false;
171
// don't compare matches
174
// if (this.size() != other.size()) return false;
175
return this.getBits().equals(other.getBits());
179
* @throws SolrException Base implementation does not allow modifications
181
public void add(int doc) {
182
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Unsupported Operation");
186
* @throws SolrException Base implementation does not allow modifications
188
public void addUnique(int doc) {
189
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Unsupported Operation");
193
* Inefficient base implementation.
195
* @see BitDocSet#getBits
197
public OpenBitSet getBits() {
198
OpenBitSet bits = new OpenBitSet();
199
for (DocIterator iter = iterator(); iter.hasNext();) {
200
bits.set(iter.nextDoc());
205
public DocSet intersection(DocSet other) {
206
// intersection is overloaded in the smaller DocSets to be more
207
// efficient, so dispatch off of it instead.
208
if (!(other instanceof BitDocSet)) {
209
return other.intersection(this);
212
// Default... handle with bitsets.
213
OpenBitSet newbits = (OpenBitSet)(this.getBits().clone());
214
newbits.and(other.getBits());
215
return new BitDocSet(newbits);
218
public DocSet union(DocSet other) {
219
OpenBitSet newbits = (OpenBitSet)(this.getBits().clone());
220
newbits.or(other.getBits());
221
return new BitDocSet(newbits);
224
public int intersectionSize(DocSet other) {
225
// intersection is overloaded in the smaller DocSets to be more
226
// efficient, so dispatch off of it instead.
227
if (!(other instanceof BitDocSet)) {
228
return other.intersectionSize(this);
230
// less efficient way: do the intersection then get it's size
231
return intersection(other).size();
234
public int unionSize(DocSet other) {
235
return this.size() + other.size() - this.intersectionSize(other);
238
public DocSet andNot(DocSet other) {
239
OpenBitSet newbits = (OpenBitSet)(this.getBits().clone());
240
newbits.andNot(other.getBits());
241
return new BitDocSet(newbits);
244
public int andNotSize(DocSet other) {
245
return this.size() - this.intersectionSize(other);
248
public Filter getTopFilter() {
249
final OpenBitSet bs = getBits();
251
return new Filter() {
253
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
255
SolrIndexReader r = (SolrIndexReader)reader;
256
while (r.getParent() != null) {
257
offset += r.getBase();
261
if (r==reader) return bs;
263
final int base = offset;
264
final int maxDoc = reader.maxDoc();
265
final int max = base + maxDoc; // one past the max doc in this segment.
267
return new DocIdSet() {
269
public DocIdSetIterator iterator() throws IOException {
270
return new DocIdSetIterator() {
280
public int nextDoc() throws IOException {
281
pos = bs.nextSetBit(pos+1);
282
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
286
public int advance(int target) throws IOException {
287
if (target==NO_MORE_DOCS) return adjustedDoc=NO_MORE_DOCS;
288
pos = bs.nextSetBit(target+base);
289
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
295
public boolean isCacheable() {