@NotNull
    DocumentCollection search(@NotNull SearchQuery query) {
        Optional<DocumentCollection> reduced;
        if (query.getOperatorType() == Operator.TYPE.DIST) {
            List<Term> terms = query.getTerms();
            List<Operator> operators = query.getOperators();

            reduced = IntStream.range(0, query.getTerms().size() - 1)
                    .mapToObj(i -> intersectDistTerms(terms.get(i), terms.get(i + 1), (CoordinateOpImpl) operators.get(i)))
                    .reduce(DocumentCollection::intersect);
        } else {
            reduced = query.getTerms().stream()
                    .map(index::findDocuments)
                    .reduce(reductionStrategy(query));
        }

        return reduced.isPresent() ? reduced.get() : new DocumentSet();
    }