private IndexSearchDescriptor findBestIndexFor ( OCommandContext ctx , Set < OIndex < ? > > indexes , OAndBlock block , OClass clazz ) { //get all valid index descriptors List < IndexSearchDescriptor > descriptors = indexes . stream ( ) . filter ( x -> x . getInternal ( ) . canBeUsedInEqualityOperators ( ) ) . map ( index -> buildIndexSearchDescriptor ( ctx , index , block , clazz ) ) . filter ( Objects :: nonNull ) . filter ( x -> x . keyCondition != null ) . filter ( x -> x . keyCondition . getSubBlocks ( ) . size ( ) > 0 ) . collect ( Collectors . toList ( ) ) ; List < IndexSearchDescriptor > fullTextIndexDescriptors = indexes . stream ( ) . filter ( idx -> idx . getType ( ) . equalsIgnoreCase ( "FULLTEXT" ) ) . filter ( idx -> ! idx . getAlgorithm ( ) . equalsIgnoreCase ( "LUCENE" ) ) . map ( idx -> buildIndexSearchDescriptorForFulltext ( ctx , idx , block , clazz ) ) . filter ( Objects :: nonNull ) . filter ( x -> x . keyCondition != null ) . filter ( x -> x . keyCondition . getSubBlocks ( ) . size ( ) > 0 ) . collect ( Collectors . toList ( ) ) ; descriptors . addAll ( fullTextIndexDescriptors ) ; //remove the redundant descriptors (eg. if I have one on [a] and one on [a, b], the first one is redundant, just discard it) descriptors = removePrefixIndexes ( descriptors ) ; //sort by cost List < OPair < Integer , IndexSearchDescriptor > > sortedDescriptors = descriptors . stream ( ) . map ( x -> ( OPair < Integer , IndexSearchDescriptor > ) new OPair ( x . cost ( ctx ) , x ) ) . sorted ( ) . collect ( Collectors . toList ( ) ) ; //get only the descriptors with the lowest cost descriptors = sortedDescriptors . isEmpty ( ) ? Collections . emptyList ( ) : sortedDescriptors . stream ( ) . filter ( x -> x . key . equals ( sortedDescriptors . get ( 0 ) . key ) ) . map ( x -> x . value ) . collect ( Collectors . toList ( ) ) ; //sort remaining by the number of indexed fields descriptors = descriptors . stream ( ) . sorted ( Comparator . comparingInt ( x -> x . keyCondition . getSubBlocks ( ) . size ( ) ) ) . collect ( Collectors . toList ( ) ) ; //get the one that has more indexed fields return descriptors . isEmpty ( ) ? null : descriptors . get ( descriptors . size ( ) - 1 ) ; }
given a flat AND block and a set of indexes returns the best index to be used to process it with the complete description on how to use it