docs: public NodeSequence fromIndex(final Index index,
                                    final long cardinalityEstimate, 
                                    final Collection<Constraint> constraints,
                                    final Collection<JoinCondition> joinConditions,
                                    final Map<String, Object> variables,
                                    final Map<String, Object> parameters,
                                    final ValueFactories valueFactories,
                                    final int batchSize) {
          if (!index.isEnabled()) {
              return null;
          }
          final IndexConstraints indexConstraints = new IndexConstraints() {
  
              @Override
              public boolean hasConstraints() {
                  return !constraints.isEmpty();
              }
  
              @Override
              public Collection<Constraint> getConstraints() {
                  return constraints;
              }
  
              @Override
              public Map<String, Object> getVariables() {
                  return variables;
              }
  
              @Override
              public ValueFactories getValueFactories() {
                  return valueFactories;
              }
  
              @Override
              public Map<String, Object> getParameters() {
                  return parameters;
              }
  
              @Override
              public Collection<JoinCondition> getJoinConditions() {
                  return joinConditions;
              }
          };
          // Return a node sequence that will lazily get the results from the index ...
          return new NodeSequence() {
              private Index.Results results;
              private Filter.ResultBatch currentBatch;
              private boolean more = true;
              private long rowCount = 0L;
  
              @Override
              public int width() {
                  return 1;
              }
  
              @Override
              public long getRowCount() {
                  if (!more) return rowCount;
                  return -1;
              }
  
              @Override
              public boolean isEmpty() {
                  if (rowCount > 0) return false;
                  if (!more) return true; // rowCount was not > 0, but there are no more
                  if (results == null) {
                      // We haven't read anything yet, so return 'false' always (even if this is not the case)
                      // so we can delay the loading of the results until really needed ...
                      return false;
                  }
                  readBatch();
                  return rowCount == 0;
              }
  
              @Override
              public Batch nextBatch() {
                  if (currentBatch == null) {
                      if (!more) {
                          // make sure we always close
                          close();
                          return null;
                      }
                      readBatch();
                  }
                  Batch nextBatch = NodeSequence.batchOfKeys(currentBatch.keys().iterator(), 
                                                             currentBatch.scores().iterator(),
                                                             currentBatch.size(),
                                                             workspaceName, repo);
                  currentBatch = null;
                  return nextBatch;
              }
  
              @Override
              public void close() {
                  if (results != null) {
                      results.close();
                      results = null;
                  }
              }
  
              protected final void readBatch() {
                  if (currentBatch != null) {
                      return;
                  }
                  currentBatch = getResults().getNextBatch(batchSize);
                  more = currentBatch.hasNext();
                  rowCount += currentBatch.size();
              }
  
              @Override
              public String toString() {
                  return "(from-index " + index.getName() + " with " + constraints + ")";
              }
  
              private Index.Results getResults() {
                  if (results != null) return results;
                  // Otherwise we have to initialize the results, so have the index do the filtering based upon the constraints ...
                  results = index.filter(indexConstraints, cardinalityEstimate);
                  return results;
              }
          };
      }