private <R> void getUnsortedChildren(final LmdbReadContext readContext,
                                         final Key parentKey,
                                         final int depth,
                                         final long limit,
                                         final OpenGroups openGroups,
                                         final TimeFilter timeFilter,
                                         final ItemMapper<R> mapper,
                                         final OffsetRange range,
                                         final FetchState fetchState,
                                         final Consumer<R> resultConsumer) {
        // Reduce the number of groups left to go into.
        openGroups.complete(parentKey);

        lmdbRowKeyFactory.createChildKeyRange(parentKey, timeFilter, keyRange ->
                readContext.read(keyRange, iterator -> {
                    long childCount = 0;

                    while (fetchState.keepGoing &&
                           childCount < limit &&
                           iterator.hasNext() &&
                           !Thread.currentThread().isInterrupted()) {

                        final KeyVal<ByteBuffer> keyVal = iterator.next();
                        // All valid keys are more than a single byte long. Single byte keys are used to store db info.
                        if (LmdbRowKeyFactoryFactory.isNotStateKey(keyVal.key())) {
                            final ByteBuffer keyBuffer = keyVal.key();
                            final ByteBuffer valueBuffer = keyVal.val();

                            // If we are just counting the total results from this point then we don't need to
                            // deserialise unless we are hiding rows.
                            if (fetchState.justCount) {
                                if (mapper.hidesRows()) {
                                    final StoredValues storedValues = readValues(valueBuffer);
                                    final Key key = lmdbRowKeyFactory.createKey(parentKey, storedValues, keyBuffer);
                                    final ItemImpl item = new ItemImpl(
                                            readContext,
                                            key,
                                            storedValues);
                                    final R row = mapper.create(item);
                                    if (row != null) {
                                        childCount++;
                                        fetchState.totalRowCount++;

                                        // Add children if the group is open.
                                        final int childDepth = depth + 1;
                                        if (openGroups.isOpen(item.getKey()) &&
                                            compiledSorters.size() > childDepth) {
                                            getUnsortedChildren(
                                                    readContext,
                                                    key,
                                                    childDepth,
                                                    maxResultSizes.size(childDepth),
                                                    openGroups,
                                                    timeFilter,
                                                    mapper,
                                                    range,
                                                    fetchState,
                                                    resultConsumer);
                                        }
                                    }
                                } else {
                                    childCount++;
                                    fetchState.totalRowCount++;

                                    // Only bother to test open groups if we have some left.
                                    if (openGroups.isNotEmpty()) {
                                        // Add children if the group is open.
                                        final StoredValues storedValues = readValues(valueBuffer);
                                        final Key key = lmdbRowKeyFactory.createKey(parentKey, storedValues, keyBuffer);
                                        final int childDepth = depth + 1;
                                        if (openGroups.isOpen(key) &&
                                            compiledSorters.size() > childDepth) {
                                            getUnsortedChildren(
                                                    readContext,
                                                    key,
                                                    childDepth,
                                                    maxResultSizes.size(childDepth),
                                                    openGroups,
                                                    timeFilter,
                                                    mapper,
                                                    range,
                                                    fetchState,
                                                    resultConsumer);
                                        }
                                    }
                                }

                            } else {
                                do {
                                    final StoredValues storedValues = readValues(valueBuffer);
                                    final Key key = lmdbRowKeyFactory.createKey(parentKey, storedValues, keyBuffer);
                                    final ItemImpl item = new ItemImpl(
                                            readContext,
                                            key,
                                            storedValues);
                                    final R row = mapper.create(item);
                                    if (row != null) {
                                        childCount++;
                                        fetchState.totalRowCount++;

                                        if (!fetchState.reachedRowLimit) {
                                            if (range.getOffset() <= fetchState.offset) {
                                                resultConsumer.accept(row);
                                                fetchState.length++;
                                                fetchState.reachedRowLimit = fetchState.length >= range.getLength();
                                                if (fetchState.reachedRowLimit) {
                                                    if (fetchState.countRows) {
                                                        fetchState.justCount = true;
                                                    } else {
                                                        fetchState.keepGoing = false;
                                                    }
                                                }
                                            }
                                            fetchState.offset++;
                                        }

                                        // Add children if the group is open.
                                        final int childDepth = depth + 1;
                                        if (fetchState.keepGoing &&
                                            openGroups.isOpen(key) &&
                                            compiledSorters.size() > childDepth) {
                                            getUnsortedChildren(
                                                    readContext,
                                                    key,
                                                    childDepth,
                                                    maxResultSizes.size(childDepth),
                                                    openGroups,
                                                    timeFilter,
                                                    mapper,
                                                    range,
                                                    fetchState,
                                                    resultConsumer);
                                        }
                                    }
                                } while (fetchState.keepGoing && valueBuffer.hasRemaining());
                            }
                        }
                    }
                }));
    }
Write data from the data store to an output removing them from the datastore as we go as they will be transferred
to another store.

@param output The output to write to.
stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/LmdbDataStore.java