ElasticsearchResponse implements Iterable<ExprValue> { public Iterator<ExprValue> iterator() { if (isAggregationResponse()) { return ElasticsearchAggregationResponseParser.parse(aggregations).stream().map(entry -> { ImmutableMap.Builder<String, ExprValue> builder = new ImmutableMap.Builder<>(); for (Map.Entry<String, Object> value : entry.entrySet()) { builder.put(value.getKey(), exprValueFactory.construct(value.getKey(), value.getValue())); } return (ExprValue) ExprTupleValue.fromExprValueMap(builder.build()); }).iterator(); } else { return Arrays.stream(hits.getHits()) .map(hit -> (ExprValue) exprValueFactory.construct(hit.getSourceAsString())).iterator(); } } ElasticsearchResponse(SearchResponse esResponse,
                               ElasticsearchExprValueFactory exprValueFactory);  ElasticsearchResponse(SearchHits hits, ElasticsearchExprValueFactory exprValueFactory); boolean isEmpty(); boolean isAggregationResponse(); Iterator<ExprValue> iterator();  }
@Test void iterator() { when(esResponse.getHits()) .thenReturn( new SearchHits( new SearchHit[] {searchHit1, searchHit2}, new TotalHits(2L, TotalHits.Relation.EQUAL_TO), 1.0F)); when(searchHit1.getSourceAsString()).thenReturn("{\"id1\", 1}"); when(searchHit2.getSourceAsString()).thenReturn("{\"id1\", 2}"); when(factory.construct(any())).thenReturn(exprTupleValue1).thenReturn(exprTupleValue2); int i = 0; for (ExprValue hit : new ElasticsearchResponse(esResponse, factory)) { if (i == 0) { assertEquals(exprTupleValue1, hit); } else if (i == 1) { assertEquals(exprTupleValue2, hit); } else { fail("More search hits returned than expected"); } i++; } }