10
10
import org .apache .lucene .store .RandomAccessInput ;
11
11
import org .opensearch .index .compositeindex .datacube .startree .node .StarTreeNode ;
12
12
import org .opensearch .index .compositeindex .datacube .startree .node .StarTreeNodeType ;
13
+ import org .opensearch .search .startree .StarTreeNodeCollector ;
13
14
14
15
import java .io .IOException ;
15
16
import java .io .UncheckedIOException ;
@@ -192,15 +193,15 @@ public StarTreeNode getChildStarNode() throws IOException {
192
193
}
193
194
194
195
@ Override
195
- public StarTreeNode getChildForDimensionValue (Long dimensionValue ) throws IOException {
196
+ public StarTreeNode getChildForDimensionValue (Long dimensionValue , StarTreeNode lastMatchedChild ) throws IOException {
196
197
// there will be no children for leaf nodes
197
198
if (isLeaf ()) {
198
199
return null ;
199
200
}
200
201
201
202
StarTreeNode resultStarTreeNode = null ;
202
203
if (null != dimensionValue ) {
203
- resultStarTreeNode = binarySearchChild (dimensionValue );
204
+ resultStarTreeNode = binarySearchChild (dimensionValue , lastMatchedChild );
204
205
}
205
206
return resultStarTreeNode ;
206
207
}
@@ -240,21 +241,29 @@ private static FixedLengthStarTreeNode matchStarTreeNodeTypeOrNull(FixedLengthSt
240
241
* @return The child node if found, null otherwise
241
242
* @throws IOException If there's an error reading from the input
242
243
*/
243
- private FixedLengthStarTreeNode binarySearchChild (long dimensionValue ) throws IOException {
244
+ private FixedLengthStarTreeNode binarySearchChild (long dimensionValue , StarTreeNode lastMatchedNode ) throws IOException {
244
245
245
246
int low = firstChildId ;
246
247
247
- // if the current node is star node, increment the low to reduce the search space
248
- if (matchStarTreeNodeTypeOrNull (new FixedLengthStarTreeNode (in , firstChildId ), StarTreeNodeType .STAR ) != null ) {
249
- low ++;
250
- }
251
-
252
248
int high = getInt (LAST_CHILD_ID_OFFSET );
253
249
// if the current node is null node, decrement the high to reduce the search space
254
250
if (matchStarTreeNodeTypeOrNull (new FixedLengthStarTreeNode (in , high ), StarTreeNodeType .NULL ) != null ) {
255
251
high --;
256
252
}
257
253
254
+ if (lastMatchedNode instanceof FixedLengthStarTreeNode ) {
255
+ int lastMatchedNodeId = ((FixedLengthStarTreeNode ) lastMatchedNode ).nodeId ();
256
+ // Start the binary search from node after the last matched as low.
257
+ if ((lastMatchedNodeId + 1 ) <= high ) {
258
+ low = lastMatchedNodeId + 1 ;
259
+ } else {
260
+ return null ;
261
+ }
262
+ } else if (matchStarTreeNodeTypeOrNull (new FixedLengthStarTreeNode (in , low ), StarTreeNodeType .STAR ) != null ) {
263
+ // if the current node is star node, increment the low to reduce the search space
264
+ low ++;
265
+ }
266
+
258
267
while (low <= high ) {
259
268
int mid = low + (high - low ) / 2 ;
260
269
FixedLengthStarTreeNode midNode = new FixedLengthStarTreeNode (in , mid );
@@ -271,6 +280,100 @@ private FixedLengthStarTreeNode binarySearchChild(long dimensionValue) throws IO
271
280
return null ;
272
281
}
273
282
283
+ @ Override
284
+ public void collectChildrenInRange (long low , long high , StarTreeNodeCollector collector ) throws IOException {
285
+ if (low <= high ) {
286
+ FixedLengthStarTreeNode lowStarTreeNode = binarySearchChild (low , true , null );
287
+ if (lowStarTreeNode != null ) {
288
+ FixedLengthStarTreeNode highStarTreeNode = binarySearchChild (high , false , lowStarTreeNode );
289
+ if (highStarTreeNode != null ) {
290
+ for (int lowNodeId = lowStarTreeNode .nodeId (); lowNodeId <= highStarTreeNode .nodeId (); ++lowNodeId ) {
291
+ collector .collectStarTreeNode (new FixedLengthStarTreeNode (in , lowNodeId ));
292
+ }
293
+ } else if (lowStarTreeNode .getDimensionValue () <= high ) { // Low StarTreeNode is the last default node for that dimension.
294
+ collector .collectStarTreeNode (lowStarTreeNode );
295
+ }
296
+ }
297
+ }
298
+ }
299
+
300
+ /**
301
+ *
302
+ * @param dimensionValue : The dimension to match.
303
+ * @param matchNextHighest : If true then we try to return @dimensionValue or the next Highest. Else, we return @dimensionValue or the next Lowest.
304
+ * @param lastMatchedNode : If not null, we begin the binary search from the node after this.
305
+ * @return : Matched node or null.
306
+ * @throws IOException :
307
+ */
308
+ private FixedLengthStarTreeNode binarySearchChild (long dimensionValue , boolean matchNextHighest , StarTreeNode lastMatchedNode )
309
+ throws IOException {
310
+
311
+ int low = firstChildId ;
312
+ int tempLow = low ;
313
+ int starNodeId , nullNodeId ;
314
+ starNodeId = nullNodeId = Integer .MIN_VALUE ;
315
+
316
+ // if the current node is star node, increment the tempLow to reduce the search space
317
+ if (matchStarTreeNodeTypeOrNull (new FixedLengthStarTreeNode (in , tempLow ), StarTreeNodeType .STAR ) != null ) {
318
+ starNodeId = tempLow ;
319
+ tempLow ++;
320
+ }
321
+
322
+ int high = getInt (LAST_CHILD_ID_OFFSET );
323
+ int tempHigh = high ;
324
+ // if the current node is null node, decrement the tempHigh to reduce the search space
325
+ if (matchStarTreeNodeTypeOrNull (new FixedLengthStarTreeNode (in , tempHigh ), StarTreeNodeType .NULL ) != null ) {
326
+ nullNodeId = tempHigh ;
327
+ tempHigh --;
328
+ }
329
+
330
+ if (lastMatchedNode instanceof FixedLengthStarTreeNode ) {
331
+ int lastMatchedNodeId = ((FixedLengthStarTreeNode ) lastMatchedNode ).nodeId ();
332
+ // Start the binary search from node after the last matched as low.
333
+ if ((lastMatchedNodeId + 1 ) <= tempHigh ) {
334
+ tempLow = lastMatchedNodeId + 1 ;
335
+ } else {
336
+ return null ;
337
+ }
338
+ }
339
+
340
+ while (tempLow <= tempHigh ) {
341
+ int mid = tempLow + (tempHigh - tempLow ) / 2 ;
342
+ FixedLengthStarTreeNode midNode = new FixedLengthStarTreeNode (in , mid );
343
+ long midDimensionValue = midNode .getDimensionValue ();
344
+
345
+ if (midDimensionValue == dimensionValue ) {
346
+ return midNode ;
347
+ } else {
348
+ if (midDimensionValue < dimensionValue ) { // Going to the right from mid to search next
349
+ tempLow = mid + 1 ;
350
+ // We are going out of bounds for this dimension on the right side.
351
+ if (tempLow > high || tempLow == nullNodeId ) {
352
+ return matchNextHighest ? null : midNode ;
353
+ } else {
354
+ FixedLengthStarTreeNode nodeGreaterThanMid = new FixedLengthStarTreeNode (in , tempLow );
355
+ if (nodeGreaterThanMid .getDimensionValue () > dimensionValue ) {
356
+ return matchNextHighest ? nodeGreaterThanMid : midNode ;
357
+ }
358
+ }
359
+ } else { // Going to the left from mid to search next
360
+ tempHigh = mid - 1 ;
361
+ // We are going out of bounds for this dimension on the left side.
362
+ if (tempHigh < low || tempHigh == starNodeId ) {
363
+ return matchNextHighest ? midNode : null ;
364
+ } else {
365
+ FixedLengthStarTreeNode nodeLessThanMid = new FixedLengthStarTreeNode (in , tempHigh );
366
+ if (nodeLessThanMid .getDimensionValue () < dimensionValue ) {
367
+ return matchNextHighest ? midNode : nodeLessThanMid ;
368
+ }
369
+ }
370
+ }
371
+ }
372
+ }
373
+ return null ;
374
+
375
+ }
376
+
274
377
@ Override
275
378
public Iterator <FixedLengthStarTreeNode > getChildrenIterator () throws IOException {
276
379
return new Iterator <>() {
@@ -297,4 +400,8 @@ public void remove() {
297
400
}
298
401
};
299
402
}
403
+
404
+ public int nodeId () {
405
+ return nodeId ;
406
+ }
300
407
}
0 commit comments