core/src/main/java/com/orientechnologies/orient/core/sql/executor/OSelectExecutionPlanner.java
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);
  }
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);
  }
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

@param ctx
@param indexes
@param block

@return
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