|
|
@@ -19,6 +19,7 @@ import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregatorFactory.ExecutionMode;
|
|
|
import org.elasticsearch.test.ESIntegTestCase;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
@@ -88,8 +89,7 @@ public class TermsDocCountErrorIT extends ESIntegTestCase {
|
|
|
.field(DOUBLE_FIELD_NAME, 1.0 * randomInt(numUniqueTerms))
|
|
|
.endObject()));
|
|
|
}
|
|
|
- assertAcked(prepareCreate("idx_fixed_docs_0").setMapping(STRING_FIELD_NAME, "type=keyword")
|
|
|
- .setSettings(Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)));
|
|
|
+
|
|
|
Map<String, Integer> shard0DocsPerTerm = new HashMap<>();
|
|
|
shard0DocsPerTerm.put("A", 25);
|
|
|
shard0DocsPerTerm.put("B", 18);
|
|
|
@@ -101,16 +101,8 @@ public class TermsDocCountErrorIT extends ESIntegTestCase {
|
|
|
shard0DocsPerTerm.put("H", 2);
|
|
|
shard0DocsPerTerm.put("I", 1);
|
|
|
shard0DocsPerTerm.put("J", 1);
|
|
|
- for (Map.Entry<String, Integer> entry : shard0DocsPerTerm.entrySet()) {
|
|
|
- for (int i = 0; i < entry.getValue(); i++) {
|
|
|
- String term = entry.getKey();
|
|
|
- builders.add(client().prepareIndex("idx_fixed_docs_0").setId(term + "-" + i)
|
|
|
- .setSource(jsonBuilder().startObject().field(STRING_FIELD_NAME, term).endObject()));
|
|
|
- }
|
|
|
- }
|
|
|
+ buildIndex(shard0DocsPerTerm, "idx_fixed_docs_0", 0, builders);
|
|
|
|
|
|
- assertAcked(prepareCreate("idx_fixed_docs_1").setMapping(STRING_FIELD_NAME, "type=keyword")
|
|
|
- .setSettings(Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)));
|
|
|
Map<String, Integer> shard1DocsPerTerm = new HashMap<>();
|
|
|
shard1DocsPerTerm.put("A", 30);
|
|
|
shard1DocsPerTerm.put("B", 25);
|
|
|
@@ -122,17 +114,8 @@ public class TermsDocCountErrorIT extends ESIntegTestCase {
|
|
|
shard1DocsPerTerm.put("Q", 6);
|
|
|
shard1DocsPerTerm.put("J", 8);
|
|
|
shard1DocsPerTerm.put("C", 4);
|
|
|
- for (Map.Entry<String, Integer> entry : shard1DocsPerTerm.entrySet()) {
|
|
|
- for (int i = 0; i < entry.getValue(); i++) {
|
|
|
- String term = entry.getKey();
|
|
|
- builders.add(client().prepareIndex("idx_fixed_docs_1").setId(term + "-" + i)
|
|
|
- .setSource(jsonBuilder().startObject().field(STRING_FIELD_NAME, term).field("shard", 1).endObject()));
|
|
|
- }
|
|
|
- }
|
|
|
+ buildIndex(shard1DocsPerTerm, "idx_fixed_docs_1", 1, builders);
|
|
|
|
|
|
- assertAcked(prepareCreate("idx_fixed_docs_2")
|
|
|
- .setMapping(STRING_FIELD_NAME, "type=keyword")
|
|
|
- .setSettings(Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)));
|
|
|
Map<String, Integer> shard2DocsPerTerm = new HashMap<>();
|
|
|
shard2DocsPerTerm.put("A", 45);
|
|
|
shard2DocsPerTerm.put("C", 44);
|
|
|
@@ -142,16 +125,49 @@ public class TermsDocCountErrorIT extends ESIntegTestCase {
|
|
|
shard2DocsPerTerm.put("H", 28);
|
|
|
shard2DocsPerTerm.put("Q", 2);
|
|
|
shard2DocsPerTerm.put("D", 1);
|
|
|
- for (Map.Entry<String, Integer> entry : shard2DocsPerTerm.entrySet()) {
|
|
|
+ buildIndex(shard2DocsPerTerm, "idx_fixed_docs_2", 2, builders);
|
|
|
+
|
|
|
+ Map<String, Integer> shard3DocsPerTerm = Map.of(
|
|
|
+ "A", 1,
|
|
|
+ "B", 1,
|
|
|
+ "C", 1
|
|
|
+ );
|
|
|
+ buildIndex(shard3DocsPerTerm, "idx_fixed_docs_3", 3, builders);
|
|
|
+
|
|
|
+ Map<String, Integer> shard4DocsPerTerm = Map.of(
|
|
|
+ "K", 1,
|
|
|
+ "L", 1,
|
|
|
+ "M", 1
|
|
|
+ );
|
|
|
+ buildIndex(shard4DocsPerTerm, "idx_fixed_docs_4", 4, builders);
|
|
|
+
|
|
|
+ Map<String, Integer> shard5DocsPerTerm = Map.of(
|
|
|
+ "X", 1,
|
|
|
+ "Y", 1,
|
|
|
+ "Z", 1
|
|
|
+ );
|
|
|
+ buildIndex(shard5DocsPerTerm, "idx_fixed_docs_5", 5, builders);
|
|
|
+
|
|
|
+ indexRandom(true, builders);
|
|
|
+ ensureSearchable();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void buildIndex(Map<String, Integer> docsPerTerm, String index, int shard, List<IndexRequestBuilder> builders)
|
|
|
+ throws IOException {
|
|
|
+ assertAcked(
|
|
|
+ prepareCreate(index).setMapping(STRING_FIELD_NAME, "type=keyword")
|
|
|
+ .setSettings(Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1))
|
|
|
+ );
|
|
|
+ for (Map.Entry<String, Integer> entry : docsPerTerm.entrySet()) {
|
|
|
for (int i = 0; i < entry.getValue(); i++) {
|
|
|
String term = entry.getKey();
|
|
|
- builders.add(client().prepareIndex("idx_fixed_docs_2").setId(term + "-" + i)
|
|
|
- .setSource(jsonBuilder().startObject().field(STRING_FIELD_NAME, term).field("shard", 2).endObject()));
|
|
|
+ builders.add(
|
|
|
+ client().prepareIndex(index)
|
|
|
+ .setId(term + "-" + i)
|
|
|
+ .setSource(jsonBuilder().startObject().field(STRING_FIELD_NAME, term).field("shard", shard).endObject())
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- indexRandom(true, builders);
|
|
|
- ensureSearchable();
|
|
|
}
|
|
|
|
|
|
private void assertDocCountErrorWithinBounds(int size, SearchResponse accurateResponse, SearchResponse testResponse) {
|
|
|
@@ -1014,4 +1030,21 @@ public class TermsDocCountErrorIT extends ESIntegTestCase {
|
|
|
assertThat(bucket.getDocCountError(), equalTo(29L));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Tests the upper bounds are correct when performing incremental reductions
|
|
|
+ * See https://github.com/elastic/elasticsearch/issues/40005 for more details
|
|
|
+ */
|
|
|
+ public void testIncrementalReduction() {
|
|
|
+ SearchResponse response = client().prepareSearch("idx_fixed_docs_3", "idx_fixed_docs_4", "idx_fixed_docs_5")
|
|
|
+ .addAggregation(terms("terms")
|
|
|
+ .executionHint(randomExecutionHint())
|
|
|
+ .field(STRING_FIELD_NAME)
|
|
|
+ .showTermDocCountError(true)
|
|
|
+ .size(5).shardSize(5)
|
|
|
+ .collectMode(randomFrom(SubAggCollectionMode.values())))
|
|
|
+ .get();
|
|
|
+ assertSearchResponse(response);
|
|
|
+ Terms terms = response.getAggregations().get("terms");
|
|
|
+ assertThat(terms.getDocCountError(), equalTo(0L));
|
|
|
+ }
|
|
|
}
|