Browse Source

DocValueFormat implementation for date range fields (#47472)

Mark Tozzi 6 years ago
parent
commit
c26ce1d7f5

+ 11 - 2
docs/reference/aggregations/bucket/range-field-note.asciidoc

@@ -117,7 +117,8 @@ POST /range_index/_search?size=0
         "november_data" : {
             "date_histogram" : {
                 "field" : "time_frame",
-                "calendar_interval" : "day"
+                "calendar_interval" : "day",
+                "format": "yyyy-MM-dd"
               }
         }
     }
@@ -135,35 +136,43 @@ calculated over the ranges of all matching documents.
   "aggregations" : {
     "november_data" : {
       "buckets" : [
-        {
+              {
+          "key_as_string" : "2019-10-28",
           "key" : 1572220800000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-10-29",
           "key" : 1572307200000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-10-30",
           "key" : 1572393600000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-10-31",
           "key" : 1572480000000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-11-01",
           "key" : 1572566400000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-11-02",
           "key" : 1572652800000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-11-03",
           "key" : 1572739200000,
           "doc_count" : 1
         },
         {
+          "key_as_string" : "2019-11-04",
           "key" : 1572825600000,
           "doc_count" : 1
         }

+ 19 - 0
server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java

@@ -45,11 +45,13 @@ import org.elasticsearch.common.xcontent.support.XContentMapValues;
 import org.elasticsearch.index.fielddata.IndexFieldData;
 import org.elasticsearch.index.fielddata.plain.DocValuesIndexFieldData;
 import org.elasticsearch.index.query.QueryShardContext;
+import org.elasticsearch.search.DocValueFormat;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -269,6 +271,23 @@ public class RangeFieldMapper extends FieldMapper {
             }
         }
 
+        @Override
+        public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
+            if (rangeType == RangeType.DATE) {
+                DateFormatter dateTimeFormatter = this.dateTimeFormatter;
+                if (format != null) {
+                    dateTimeFormatter = DateFormatter.forPattern(format).withLocale(dateTimeFormatter.locale());
+                }
+                if (timeZone == null) {
+                    timeZone = ZoneOffset.UTC;
+                }
+                // the resolution here is always set to milliseconds, as aggregations use this formatter mainly and those are always in
+                // milliseconds. The only special case here is docvalue fields, which are handled somewhere else
+                return new DocValueFormat.DateTime(dateTimeFormatter, timeZone, DateFieldMapper.Resolution.MILLISECONDS);
+            }
+            return super.docValueFormat(format, timeZone);
+        }
+
         @Override
         public Query termQuery(Object value, QueryShardContext context) {
             Query query = rangeQuery(value, value, true, true, ShapeRelation.INTERSECTS, null, null, context);

+ 16 - 0
server/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/DateRangeHistogramAggregatorTests.java

@@ -65,6 +65,22 @@ public class DateRangeHistogramAggregatorTests extends AggregatorTestCase {
         );
     }
 
+    public void testFormat() throws Exception {
+        RangeFieldMapper.Range range = new RangeFieldMapper.Range(RangeType.DATE, asLong("2019-08-01T12:14:36"),
+            asLong("2019-08-01T15:07:22"), true, true);
+        testCase(
+            new MatchAllDocsQuery(),
+            builder -> builder.calendarInterval(DateHistogramInterval.DAY).format("yyyy-MM-dd"),
+            writer -> writer.addDocument(singleton(new BinaryDocValuesField(FIELD_NAME, RangeType.DATE.encodeRanges(singleton(range))))),
+            histo -> {
+                assertEquals(1, histo.getBuckets().size());
+                assertTrue(AggregationInspectionHelper.hasValue(histo));
+
+                assertEquals("2019-08-01", histo.getBuckets().get(0).getKeyAsString());
+            }
+        );
+    }
+
     public void testUnsupportedRangeType() throws Exception {
         RangeType rangeType = RangeType.LONG;
         final String fieldName = "field";