private void processResultBatch(final FieldIndex fieldIndex,
                                    final ResultStore resultStore,
                                    final ValuesConsumer valuesConsumer,
                                    final ErrorConsumer errorConsumer,
                                    final AtomicLong hitCount,
                                    final List<Hit<ObjectNode>> searchHits) {
        try {
            for (final Hit<ObjectNode> searchHit : searchHits) {
                hitCount.incrementAndGet();

                // Add highlights
                if (elasticSearchConfigProvider.get().getHighlight()) {
                    for (final List<String> highlightField : searchHit.highlight().values()) {
                        resultStore.addHighlights(Set.copyOf(highlightField));
                    }
                }

                final Map<String, JsonData> mapSearchHit = searchHit.fields();
                Val[] values = null;

                for (final String fieldName : fieldIndex.getFields()) {
                    final Integer insertAt = fieldIndex.getPos(fieldName);
                    Object fieldValue = getFieldValue(mapSearchHit, fieldName);

                    if (fieldValue != null) {
                        if (values == null) {
                            values = new Val[fieldIndex.size()];
                        }

                        if (fieldValue instanceof Long) {
                            // TODO Need to handle date fields as ValDate, assuming they come in as longs,
                            //  but we need the field type from somewhere
                            values[insertAt] = ValLong.create((Long) fieldValue);
                        } else if (fieldValue instanceof Integer) {
                            values[insertAt] = ValInteger.create((Integer) fieldValue);
                        } else if (fieldValue instanceof Double) {
                            values[insertAt] = ValDouble.create((Double) fieldValue);
                        } else if (fieldValue instanceof Float) {
                            values[insertAt] = ValDouble.create((Float) fieldValue);
                        } else if (fieldValue instanceof Boolean) {
                            values[insertAt] = ValBoolean.create((Boolean) fieldValue);
                        } else if (fieldValue instanceof ArrayList) {
                            values[insertAt] = ValString.create(((ArrayList<?>) fieldValue).stream()
                                    .map(Object::toString)
                                    .collect(Collectors.joining(", ")));
                        } else {
                            values[insertAt] = ValString.create(fieldValue.toString());
                        }
                    }
                }

                if (values != null) {
                    valuesConsumer.accept(Val.of(values));
                }
            }
        } catch (final UncheckedInterruptedException e) {
            throw e;
        } catch (final RuntimeException e) {
            error(errorConsumer, e);
        }
    }
Receive a batch of search hits and send each one to the values consumer
stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java