Skip to content

Commit 14b8114

Browse files
author
Christoph Büscher
authored
Preserve date_histogram format when aggregating on unmapped fields (#35254)
Currently when aggregating on an unmapped date field (e.g. using a date_histogram) we don't preserve the aggregations `format` setting but instead use the default format. This can lead to loosing the aggregations `format` when aggregating over several indices where some of them contain unmapped date fields and are encountered first in the reduce phase. Related to #31760
1 parent 0b24c4f commit 14b8114

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceConfig.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.lucene.util.BytesRef;
2222
import org.elasticsearch.common.Nullable;
2323
import org.elasticsearch.common.geo.GeoPoint;
24+
import org.elasticsearch.common.joda.Joda;
2425
import org.elasticsearch.index.fielddata.IndexFieldData;
2526
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
2627
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
@@ -53,7 +54,7 @@ public static <VS extends ValuesSource> ValuesSourceConfig<VS> resolve(
5354
if (field == null) {
5455
if (script == null) {
5556
ValuesSourceConfig<VS> config = new ValuesSourceConfig<>(ValuesSourceType.ANY);
56-
config.format(resolveFormat(null, valueType));
57+
config.format(resolveFormat(null, valueType, timeZone));
5758
return config;
5859
}
5960
ValuesSourceType valuesSourceType = valueType != null ? valueType.getValuesSourceType() : ValuesSourceType.ANY;
@@ -67,7 +68,7 @@ public static <VS extends ValuesSource> ValuesSourceConfig<VS> resolve(
6768
ValuesSourceConfig<VS> config = new ValuesSourceConfig<>(valuesSourceType);
6869
config.missing(missing);
6970
config.timezone(timeZone);
70-
config.format(resolveFormat(format, valueType));
71+
config.format(resolveFormat(format, valueType, timeZone));
7172
config.script(createScript(script, context));
7273
config.scriptValueType(valueType);
7374
return config;
@@ -79,7 +80,7 @@ public static <VS extends ValuesSource> ValuesSourceConfig<VS> resolve(
7980
ValuesSourceConfig<VS> config = new ValuesSourceConfig<>(valuesSourceType);
8081
config.missing(missing);
8182
config.timezone(timeZone);
82-
config.format(resolveFormat(format, valueType));
83+
config.format(resolveFormat(format, valueType, timeZone));
8384
config.unmapped(true);
8485
if (valueType != null) {
8586
// todo do we really need this for unmapped?
@@ -120,14 +121,17 @@ private static AggregationScript.LeafFactory createScript(Script script, QuerySh
120121
}
121122
}
122123

123-
private static DocValueFormat resolveFormat(@Nullable String format, @Nullable ValueType valueType) {
124+
private static DocValueFormat resolveFormat(@Nullable String format, @Nullable ValueType valueType, @Nullable DateTimeZone tz) {
124125
if (valueType == null) {
125126
return DocValueFormat.RAW; // we can't figure it out
126127
}
127128
DocValueFormat valueFormat = valueType.defaultFormat;
128129
if (valueFormat instanceof DocValueFormat.Decimal && format != null) {
129130
valueFormat = new DocValueFormat.Decimal(format);
130131
}
132+
if (valueFormat instanceof DocValueFormat.DateTime && format != null) {
133+
valueFormat = new DocValueFormat.DateTime(Joda.forPattern(format), tz != null ? tz : DateTimeZone.UTC);
134+
}
131135
return valueFormat;
132136
}
133137

server/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,31 @@ public void testExceptionOnNegativeInterval() {
13411341
}
13421342
}
13431343

1344+
/**
1345+
* https://github.com/elastic/elasticsearch/issues/31760 shows an edge case where an unmapped "date" field in two indices
1346+
* that are queried simultaneously can lead to the "format" parameter in the aggregation not being preserved correctly.
1347+
*
1348+
* The error happens when the bucket from the "unmapped" index is received first in the reduce phase, however the case can
1349+
* be recreated when aggregating about a single index with an unmapped date field and also getting "empty" buckets.
1350+
*/
1351+
public void testFormatIndexUnmapped() throws InterruptedException, ExecutionException {
1352+
String indexDateUnmapped = "test31760";
1353+
indexRandom(true, client().prepareIndex(indexDateUnmapped, "_doc").setSource("foo", "bar"));
1354+
ensureSearchable(indexDateUnmapped);
1355+
1356+
SearchResponse response = client().prepareSearch(indexDateUnmapped)
1357+
.addAggregation(
1358+
dateHistogram("histo").field("dateField").dateHistogramInterval(DateHistogramInterval.MONTH).format("YYYY-MM")
1359+
.minDocCount(0).extendedBounds(new ExtendedBounds("2018-01", "2018-01")))
1360+
.execute().actionGet();
1361+
assertSearchResponse(response);
1362+
Histogram histo = response.getAggregations().get("histo");
1363+
assertThat(histo.getBuckets().size(), equalTo(1));
1364+
assertThat(histo.getBuckets().get(0).getKeyAsString(), equalTo("2018-01"));
1365+
assertThat(histo.getBuckets().get(0).getDocCount(), equalTo(0L));
1366+
internalCluster().wipeIndices(indexDateUnmapped);
1367+
}
1368+
13441369
/**
13451370
* https://github.com/elastic/elasticsearch/issues/31392 demonstrates an edge case where a date field mapping with
13461371
* "format" = "epoch_millis" can lead for the date histogram aggregation to throw an error if a non-UTC time zone

0 commit comments

Comments
 (0)