10
10
11
11
import org .opensearch .common .Rounding ;
12
12
import org .opensearch .common .annotation .ExperimentalApi ;
13
+ import org .opensearch .common .time .DateUtils ;
13
14
import org .opensearch .core .xcontent .XContentBuilder ;
15
+ import org .opensearch .index .compositeindex .datacube .startree .utils .date .DateTimeUnitRounding ;
14
16
import org .opensearch .index .mapper .CompositeDataCubeFieldType ;
17
+ import org .opensearch .index .mapper .DateFieldMapper ;
15
18
16
19
import java .io .IOException ;
20
+ import java .util .ArrayList ;
21
+ import java .util .Comparator ;
22
+ import java .util .HashMap ;
17
23
import java .util .List ;
24
+ import java .util .Map ;
18
25
import java .util .Objects ;
26
+ import java .util .function .Consumer ;
27
+ import java .util .stream .Collectors ;
19
28
20
29
/**
21
30
* Date dimension class
24
33
*/
25
34
@ ExperimentalApi
26
35
public class DateDimension implements Dimension {
27
- private final List <Rounding . DateTimeUnit > calendarIntervals ;
36
+ private final List <DateTimeUnitRounding > calendarIntervals ;
28
37
public static final String CALENDAR_INTERVALS = "calendar_intervals" ;
29
38
public static final String DATE = "date" ;
30
39
private final String field ;
40
+ private final List <DateTimeUnitRounding > sortedCalendarIntervals ;
41
+ private final DateFieldMapper .Resolution resolution ;
31
42
32
- public DateDimension (String field , List <Rounding . DateTimeUnit > calendarIntervals ) {
43
+ public DateDimension (String field , List <DateTimeUnitRounding > calendarIntervals , DateFieldMapper . Resolution resolution ) {
33
44
this .field = field ;
34
45
this .calendarIntervals = calendarIntervals ;
46
+ // Sort from the lowest unit to the highest unit
47
+ this .sortedCalendarIntervals = getSortedDateTimeUnits (calendarIntervals );
48
+ if (resolution == null ) {
49
+ this .resolution = DateFieldMapper .Resolution .MILLISECONDS ;
50
+ } else {
51
+ this .resolution = resolution ;
52
+ }
35
53
}
36
54
37
- public List <Rounding . DateTimeUnit > getIntervals () {
55
+ public List <DateTimeUnitRounding > getIntervals () {
38
56
return calendarIntervals ;
39
57
}
40
58
59
+ public List <DateTimeUnitRounding > getSortedCalendarIntervals () {
60
+ return sortedCalendarIntervals ;
61
+ }
62
+
63
+ /**
64
+ * Sets the dimension values in sorted order in the provided array starting from the given index.
65
+ *
66
+ * @param val The value to be set
67
+ * @param dimSetter Consumer which sets the dimensions
68
+ */
69
+ @ Override
70
+ public void setDimensionValues (final Long val , final Consumer <Long > dimSetter ) {
71
+ for (DateTimeUnitRounding dateTimeUnit : sortedCalendarIntervals ) {
72
+ if (val == null ) {
73
+ dimSetter .accept (null );
74
+ } else {
75
+ Long roundedValue = dateTimeUnit .roundFloor (storedDurationSinceEpoch (val ));
76
+ dimSetter .accept (roundedValue );
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Converts nanoseconds to milliseconds based on the resolution of the field
83
+ */
84
+ private long storedDurationSinceEpoch (long nanoSecondsSinceEpoch ) {
85
+ if (resolution .equals (DateFieldMapper .Resolution .NANOSECONDS )) return DateUtils .toMilliSeconds (nanoSecondsSinceEpoch );
86
+ return nanoSecondsSinceEpoch ;
87
+ }
88
+
89
+ /**
90
+ * Returns the list of fields that represent the dimension
91
+ */
92
+ @ Override
93
+ public List <String > getSubDimensionNames () {
94
+ List <String > fields = new ArrayList <>(calendarIntervals .size ());
95
+ for (DateTimeUnitRounding interval : sortedCalendarIntervals ) {
96
+ fields .add (field + "_" + interval .shortName ());
97
+ }
98
+ return fields ;
99
+ }
100
+
41
101
@ Override
42
102
public XContentBuilder toXContent (XContentBuilder builder , Params params ) throws IOException {
43
- builder .startObject ();
103
+ builder .startObject ("date_dimension" );
44
104
builder .field (CompositeDataCubeFieldType .NAME , this .getField ());
45
105
builder .field (CompositeDataCubeFieldType .TYPE , DATE );
46
106
builder .startArray (CALENDAR_INTERVALS );
47
- for (Rounding . DateTimeUnit interval : calendarIntervals ) {
107
+ for (DateTimeUnitRounding interval : calendarIntervals ) {
48
108
builder .value (interval .shortName ());
49
109
}
50
110
builder .endArray ();
@@ -69,4 +129,44 @@ public int hashCode() {
69
129
public String getField () {
70
130
return field ;
71
131
}
132
+
133
+ @ Override
134
+ public int getNumSubDimensions () {
135
+ return calendarIntervals .size ();
136
+ }
137
+
138
+ /**
139
+ * DateTimeUnit Comparator which tracks dateTimeUnits in sorted order from second unit to year unit
140
+ */
141
+ public static class DateTimeUnitComparator implements Comparator <DateTimeUnitRounding > {
142
+ public static final Map <String , Integer > ORDERED_DATE_TIME_UNIT = new HashMap <>();
143
+
144
+ static {
145
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .SECOND_OF_MINUTE .shortName (), 1 );
146
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .MINUTES_OF_HOUR .shortName (), 2 );
147
+ ORDERED_DATE_TIME_UNIT .put (DataCubeDateTimeUnit .QUARTER_HOUR_OF_DAY .shortName (), 3 );
148
+ ORDERED_DATE_TIME_UNIT .put (DataCubeDateTimeUnit .HALF_HOUR_OF_DAY .shortName (), 4 );
149
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .HOUR_OF_DAY .shortName (), 5 );
150
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .DAY_OF_MONTH .shortName (), 6 );
151
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .WEEK_OF_WEEKYEAR .shortName (), 7 );
152
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .MONTH_OF_YEAR .shortName (), 8 );
153
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .QUARTER_OF_YEAR .shortName (), 9 );
154
+ ORDERED_DATE_TIME_UNIT .put (Rounding .DateTimeUnit .YEAR_OF_CENTURY .shortName (), 10 );
155
+ }
156
+
157
+ @ Override
158
+ public int compare (DateTimeUnitRounding unit1 , DateTimeUnitRounding unit2 ) {
159
+ return Integer .compare (
160
+ ORDERED_DATE_TIME_UNIT .getOrDefault (unit1 .shortName (), Integer .MAX_VALUE ),
161
+ ORDERED_DATE_TIME_UNIT .getOrDefault (unit2 .shortName (), Integer .MAX_VALUE )
162
+ );
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Returns a sorted list of dateTimeUnits based on the DateTimeUnitComparator
168
+ */
169
+ public static List <DateTimeUnitRounding > getSortedDateTimeUnits (List <DateTimeUnitRounding > dateTimeUnits ) {
170
+ return dateTimeUnits .stream ().sorted (new DateTimeUnitComparator ()).collect (Collectors .toList ());
171
+ }
72
172
}
0 commit comments