package pl.allegro.tech.search.elasticsearch.tools.reindex.process;
import com.google.common.collect.ImmutableMap;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.unit.TimeValue;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import pl.allegro.tech.search.elasticsearch.tools.reindex.connection.ElasticDataPointer;
import pl.allegro.tech.search.elasticsearch.tools.reindex.connection.ElasticSearchClientFactory;
import pl.allegro.tech.search.elasticsearch.tools.reindex.connection.ElasticSearchQuery;
import pl.allegro.tech.search.elasticsearch.tools.reindex.embeded.EmbeddedElasticsearchCluster;
import pl.allegro.tech.search.elasticsearch.tools.reindex.embeded.IndexDocument;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static org.junit.Assert.*;
public class QueryComponentTest {
private static final String SOURCE_INDEX = "sourceindex";
private static final String TARGET_INDEX = "targetindex";
public static final String DATA_TYPE = "type";
private static EmbeddedElasticsearchCluster embeddedElasticsearchCluster;
@BeforeClass
public static void setUp() throws Exception {
embeddedElasticsearchCluster = EmbeddedElasticsearchCluster.createDataNode();
}
@AfterClass
public static void tearDown() throws Exception {
embeddedElasticsearchCluster.close();
}
@Before
public void clearTargetIndex() {
embeddedElasticsearchCluster.deleteIndex(SOURCE_INDEX);
embeddedElasticsearchCluster.deleteIndex(TARGET_INDEX);
}
@Test
public void testQueryNoData() {
// given
embeddedElasticsearchCluster.recreateIndex(SOURCE_INDEX);
ElasticDataPointer sourceDataPointer = embeddedElasticsearchCluster.createDataPointer(SOURCE_INDEX);
Client sourceClient = ElasticSearchClientFactory.createClient(sourceDataPointer);
ElasticSearchQuery elasticSearchQuery = embeddedElasticsearchCluster.createInitialQuery("");
// when
QueryComponent component = QueryComponentBuilder.builder()
.setClient(sourceClient)
.setDataPointer(sourceDataPointer)
.setQuery(elasticSearchQuery)
.createQueryComponent();
SearchResponse searchResponse = component.prepareSearchScrollRequest();
// then
assertEquals("No results overall",
0L, searchResponse.getHits().getTotalHits());
assertEquals("Initially zero documents are loaded",
0L, searchResponse.getHits().getHits().length);
assertEquals("Initially zero documents are loaded",
0L, component.getResponseSize(searchResponse));
assertFalse("Some documents are found",
component.searchResultsNotEmpty(searchResponse));
// when
searchResponse = component.getNextScrolledSearchResults(searchResponse.getScrollId());
// then
assertEquals("No results overall",
0L, searchResponse.getHits().getTotalHits());
assertEquals("Initially zero documents are loaded",
0L, searchResponse.getHits().getHits().length);
assertEquals("Initially zero documents are loaded",
0L, component.getResponseSize(searchResponse));
assertFalse("Some documents are found",
component.searchResultsNotEmpty(searchResponse));
}
@Test
public void testQueryWithData() {
// given
indexWithSampleData(7000);
ElasticDataPointer sourceDataPointer = embeddedElasticsearchCluster.createDataPointer(SOURCE_INDEX);
Client sourceClient = ElasticSearchClientFactory.createClient(sourceDataPointer);
ElasticSearchQuery elasticSearchQuery = embeddedElasticsearchCluster.createInitialQuery("");
GetSettingsResponse indexSettings = sourceClient.admin().indices().getSettings(new GetSettingsRequest().indices(SOURCE_INDEX)).actionGet();
assertEquals("We should have an index with 5 shards now",
"5", indexSettings.getIndexToSettings().get(SOURCE_INDEX).get("index.number_of_shards"));
assertEquals("We should have an index with one replica now",
"1", indexSettings.getIndexToSettings().get(SOURCE_INDEX).get("index.number_of_replicas"));
// when
QueryComponent component = QueryComponentBuilder.builder()
.setClient(sourceClient)
.setDataPointer(sourceDataPointer)
.setQuery(elasticSearchQuery)
.createQueryComponent();
SearchResponse searchResponse = component.prepareSearchScrollRequest();
// then
assertEquals("Overall there should be 7000 hits",
7000L, searchResponse.getHits().getTotalHits());
assertEquals("Initially zero documents are loaded",
0L, searchResponse.getHits().getHits().length);
assertEquals("Initially zero documents are loaded",
0L, component.getResponseSize(searchResponse));
assertTrue("Some documents are found",
component.searchResultsNotEmpty(searchResponse));
// when
searchResponse = component.getNextScrolledSearchResults(searchResponse.getScrollId());
// then
assertEquals("Overall there should be 7000 hits",
7000L, searchResponse.getHits().getTotalHits());
assertEquals("QueryComponent tries to compute the hits to be 5000 on evenly distributed documents, never more!",
5000L, searchResponse.getHits().getHits().length);
assertEquals("QueryComponent tries to compute the hits to be 5000 on evenly distributed documents, never more!",
5000L, component.getResponseSize(searchResponse));
assertTrue("Some documents are found",
component.searchResultsNotEmpty(searchResponse));
}
// just a simple test to verify that replica-shards are not included in the calculation of results
// for the "size per shard" setting in scan/scroll-queries
@Test
public void testElasticsearchReplicaHandlingInScrolls() {
// given
indexWithSampleData(200);
ElasticDataPointer sourceDataPointer = embeddedElasticsearchCluster.createDataPointer(SOURCE_INDEX);
Client sourceClient = ElasticSearchClientFactory.createClient(sourceDataPointer);
GetSettingsResponse indexSettings = sourceClient.admin().indices().getSettings(new GetSettingsRequest().indices(SOURCE_INDEX)).actionGet();
assertEquals("We should have an index with 5 shards now",
"5", indexSettings.getIndexToSettings().get(SOURCE_INDEX).get("index.number_of_shards"));
assertEquals("We should have an index with one replica now",
"1", indexSettings.getIndexToSettings().get(SOURCE_INDEX).get("index.number_of_replicas"));
// when
SearchRequestBuilder searchRequestBuilder = sourceClient.prepareSearch(sourceDataPointer.getIndexName())
.setTypes(DATA_TYPE)
.setSearchType(SearchType.SCAN)
.addFields("_ttl", "_source")
.setScroll(new TimeValue(QueryComponent.SCROLL_TIME_LIMIT))
.setSize(10);
assertNotNull(searchRequestBuilder);
// then
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
assertEquals("Overall there should be 200 hits",
200L, searchResponse.getHits().getTotalHits());
assertEquals("Initially zero documents are loaded",
0L, searchResponse.getHits().getHits().length);
// when
searchResponse = sourceClient.prepareSearchScroll(searchResponse.getScrollId())
.setScroll(new TimeValue(QueryComponent.SCROLL_TIMEOUT))
.get();
// then
assertEquals(200L, searchResponse.getHits().getTotalHits());
assertEquals(50L, searchResponse.getHits().getHits().length);
}
private void indexWithSampleData(final int numberOfDocuments) {
Stream<IndexDocument> streamToBeIndexed = IntStream
.range(1, numberOfDocuments+1)
.mapToObj(
i -> new IndexDocument(Integer.toString(i), ImmutableMap.of("fieldName", i))
);
embeddedElasticsearchCluster.indexWithSampleData(SOURCE_INDEX, DATA_TYPE, streamToBeIndexed);
}
}