29
29
import org .apache .lucene .util .BytesRefIterator ;
30
30
import org .apache .lucene .util .DocIdSetBuilder ;
31
31
import org .apache .lucene .util .RamUsageEstimator ;
32
- import org .roaringbitmap .RoaringBitmap ;
33
32
34
33
import java .io .IOException ;
35
- import java .util .Iterator ;
36
34
import java .util .Objects ;
37
35
36
+ import org .roaringbitmap .PeekableIntIterator ;
37
+ import org .roaringbitmap .RoaringBitmap ;
38
+
38
39
/**
39
40
* A query that matches all documents that contain a set of integer numbers represented by bitmap
40
41
*
@@ -50,12 +51,19 @@ public BitmapIndexQuery(String field, RoaringBitmap bitmap) {
50
51
this .field = field ;
51
52
}
52
53
53
- private static BytesRefIterator bitmapEncodedIterator (RoaringBitmap bitmap ) {
54
- return new BytesRefIterator () {
55
- private final Iterator <Integer > iterator = bitmap .iterator ();
54
+ interface BitmapIterator extends BytesRefIterator {
55
+ // wrap IntIterator.next()
56
+ BytesRef next ();
57
+
58
+ // expose PeekableIntIterator.advanceIfNeeded, advance as long as the next value is smaller than target
59
+ void advance (byte [] target );
60
+ }
61
+
62
+ private static BitmapIterator bitmapEncodedIterator (RoaringBitmap bitmap ) {
63
+ return new BitmapIterator () {
64
+ private final PeekableIntIterator iterator = bitmap .getIntIterator ();
56
65
private final BytesRef encoded = new BytesRef (new byte [Integer .BYTES ]);
57
66
58
- @ Override
59
67
public BytesRef next () {
60
68
int value ;
61
69
if (iterator .hasNext ()) {
@@ -66,6 +74,10 @@ public BytesRef next() {
66
74
IntPoint .encodeDimension (value , encoded .bytes , 0 );
67
75
return encoded ;
68
76
}
77
+
78
+ public void advance (byte [] target ) {
79
+ iterator .advanceIfNeeded (IntPoint .decodeDimension (target , 0 ));
80
+ }
69
81
};
70
82
}
71
83
@@ -85,8 +97,7 @@ public Scorer scorer(LeafReaderContext context) throws IOException {
85
97
public ScorerSupplier scorerSupplier (LeafReaderContext context ) throws IOException {
86
98
final Weight weight = this ;
87
99
LeafReader reader = context .reader ();
88
- // get point value
89
- // only works for one dimension
100
+ // get the point value which should be one dimension, since bitmap saves integers
90
101
PointValues values = reader .getPointValues (field );
91
102
if (values == null ) {
92
103
return null ;
@@ -118,21 +129,20 @@ public long cost() {
118
129
119
130
@ Override
120
131
public boolean isCacheable (LeafReaderContext ctx ) {
121
- // This query depend only on segment-immutable structure points
132
+ // This query depend only on segment-immutable structure — points
122
133
return true ;
123
134
}
124
135
};
125
136
}
126
137
127
138
private class MergePointVisitor implements PointValues .IntersectVisitor {
128
139
private final DocIdSetBuilder result ;
129
- private final BytesRefIterator iterator ;
140
+ private final BitmapIterator iterator ;
130
141
private BytesRef nextQueryPoint ;
131
142
private final ArrayUtil .ByteArrayComparator comparator ;
132
143
private DocIdSetBuilder .BulkAdder adder ;
133
144
134
- public MergePointVisitor (DocIdSetBuilder result )
135
- throws IOException {
145
+ public MergePointVisitor (DocIdSetBuilder result ) throws IOException {
136
146
this .result = result ;
137
147
this .comparator = ArrayUtil .getUnsignedComparator (Integer .BYTES );
138
148
this .iterator = bitmapEncodedIterator (bitmap );
@@ -175,11 +185,8 @@ private boolean matches(byte[] packedValue) {
175
185
return true ;
176
186
} else if (cmp < 0 ) {
177
187
// Query point is before index point, so we move to next query point
178
- try {
179
- nextQueryPoint = iterator .next ();
180
- } catch (IOException e ) {
181
- throw new RuntimeException (e );
182
- }
188
+ iterator .advance (packedValue );
189
+ nextQueryPoint = iterator .next ();
183
190
} else {
184
191
// Query point is after index point, so we don't collect and we return:
185
192
break ;
@@ -191,19 +198,14 @@ private boolean matches(byte[] packedValue) {
191
198
@ Override
192
199
public PointValues .Relation compare (byte [] minPackedValue , byte [] maxPackedValue ) {
193
200
while (nextQueryPoint != null ) {
194
- int cmpMin =
195
- comparator .compare (nextQueryPoint .bytes , nextQueryPoint .offset , minPackedValue , 0 );
201
+ int cmpMin = comparator .compare (nextQueryPoint .bytes , nextQueryPoint .offset , minPackedValue , 0 );
196
202
if (cmpMin < 0 ) {
197
203
// query point is before the start of this cell
198
- try {
199
- nextQueryPoint = iterator .next ();
200
- } catch (IOException e ) {
201
- throw new RuntimeException (e );
202
- }
204
+ iterator .advance (minPackedValue );
205
+ nextQueryPoint = iterator .next ();
203
206
continue ;
204
207
}
205
- int cmpMax =
206
- comparator .compare (nextQueryPoint .bytes , nextQueryPoint .offset , maxPackedValue , 0 );
208
+ int cmpMax = comparator .compare (nextQueryPoint .bytes , nextQueryPoint .offset , maxPackedValue , 0 );
207
209
if (cmpMax > 0 ) {
208
210
// query point is after the end of this cell
209
211
return PointValues .Relation .CELL_OUTSIDE_QUERY ;
@@ -260,7 +262,7 @@ public int hashCode() {
260
262
261
263
@ Override
262
264
public long ramBytesUsed () {
263
- return RamUsageEstimator .shallowSizeOfInstance (BitmapIndexQuery .class ) + RamUsageEstimator .sizeOfObject (field )
264
- + RamUsageEstimator .sizeOfObject (bitmap );
265
+ return RamUsageEstimator .shallowSizeOfInstance (BitmapIndexQuery .class ) + RamUsageEstimator .sizeOfObject (field ) + RamUsageEstimator
266
+ .sizeOfObject (bitmap );
265
267
}
266
268
}
0 commit comments