1717
1818import java .util .Optional ;
1919
20+ import org .springframework .data .mongodb .core .mapping .Field ;
2021import org .springframework .data .mongodb .core .query .Collation ;
2122import org .springframework .data .mongodb .core .schema .MongoJsonSchema ;
23+ import org .springframework .data .mongodb .core .timeseries .Granularities ;
24+ import org .springframework .data .mongodb .core .timeseries .Granularity ;
2225import org .springframework .data .mongodb .core .validation .Validator ;
2326import org .springframework .data .util .Optionals ;
2427import org .springframework .lang .Nullable ;
@@ -42,6 +45,7 @@ public class CollectionOptions {
4245 private @ Nullable Boolean capped ;
4346 private @ Nullable Collation collation ;
4447 private ValidationOptions validationOptions ;
48+ private @ Nullable TimeSeriesOptions timeSeriesOptions ;
4549
4650 /**
4751 * Constructs a new <code>CollectionOptions</code> instance.
@@ -54,17 +58,19 @@ public class CollectionOptions {
5458 */
5559 @ Deprecated
5660 public CollectionOptions (@ Nullable Long size , @ Nullable Long maxDocuments , @ Nullable Boolean capped ) {
57- this (size , maxDocuments , capped , null , ValidationOptions .none ());
61+ this (size , maxDocuments , capped , null , ValidationOptions .none (), null );
5862 }
5963
6064 private CollectionOptions (@ Nullable Long size , @ Nullable Long maxDocuments , @ Nullable Boolean capped ,
61- @ Nullable Collation collation , ValidationOptions validationOptions ) {
65+ @ Nullable Collation collation , ValidationOptions validationOptions ,
66+ @ Nullable TimeSeriesOptions timeSeriesOptions ) {
6267
6368 this .maxDocuments = maxDocuments ;
6469 this .size = size ;
6570 this .capped = capped ;
6671 this .collation = collation ;
6772 this .validationOptions = validationOptions ;
73+ this .timeSeriesOptions = timeSeriesOptions ;
6874 }
6975
7076 /**
@@ -78,7 +84,7 @@ public static CollectionOptions just(Collation collation) {
7884
7985 Assert .notNull (collation , "Collation must not be null!" );
8086
81- return new CollectionOptions (null , null , null , collation , ValidationOptions .none ());
87+ return new CollectionOptions (null , null , null , collation , ValidationOptions .none (), null );
8288 }
8389
8490 /**
@@ -88,7 +94,21 @@ public static CollectionOptions just(Collation collation) {
8894 * @since 2.0
8995 */
9096 public static CollectionOptions empty () {
91- return new CollectionOptions (null , null , null , null , ValidationOptions .none ());
97+ return new CollectionOptions (null , null , null , null , ValidationOptions .none (), null );
98+ }
99+
100+ /**
101+ * Quick way to set up {@link CollectionOptions} for a Time Series collection. For more advanced settings use
102+ * {@link #timeSeries(TimeSeriesOptions)}.
103+ *
104+ * @param timeField The name of the property which contains the date in each time series document. Must not be
105+ * {@literal null}.
106+ * @return new instance of {@link CollectionOptions}.
107+ * @see #timeSeries(TimeSeriesOptions)
108+ * @since 3.3
109+ */
110+ public static CollectionOptions timeSeries (String timeField ) {
111+ return empty ().timeSeries (TimeSeriesOptions .timeSeries (timeField ));
92112 }
93113
94114 /**
@@ -99,7 +119,7 @@ public static CollectionOptions empty() {
99119 * @since 2.0
100120 */
101121 public CollectionOptions capped () {
102- return new CollectionOptions (size , maxDocuments , true , collation , validationOptions );
122+ return new CollectionOptions (size , maxDocuments , true , collation , validationOptions , null );
103123 }
104124
105125 /**
@@ -110,7 +130,7 @@ public CollectionOptions capped() {
110130 * @since 2.0
111131 */
112132 public CollectionOptions maxDocuments (long maxDocuments ) {
113- return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions );
133+ return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions , timeSeriesOptions );
114134 }
115135
116136 /**
@@ -121,7 +141,7 @@ public CollectionOptions maxDocuments(long maxDocuments) {
121141 * @since 2.0
122142 */
123143 public CollectionOptions size (long size ) {
124- return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions );
144+ return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions , timeSeriesOptions );
125145 }
126146
127147 /**
@@ -132,7 +152,7 @@ public CollectionOptions size(long size) {
132152 * @since 2.0
133153 */
134154 public CollectionOptions collation (@ Nullable Collation collation ) {
135- return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions );
155+ return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions , timeSeriesOptions );
136156 }
137157
138158 /**
@@ -252,7 +272,20 @@ public CollectionOptions schemaValidationAction(ValidationAction validationActio
252272 public CollectionOptions validation (ValidationOptions validationOptions ) {
253273
254274 Assert .notNull (validationOptions , "ValidationOptions must not be null!" );
255- return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions );
275+ return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions , timeSeriesOptions );
276+ }
277+
278+ /**
279+ * Create new {@link CollectionOptions} with the given {@link TimeSeriesOptions}.
280+ *
281+ * @param timeSeriesOptions must not be {@literal null}.
282+ * @return new instance of {@link CollectionOptions}.
283+ * @since 3.3
284+ */
285+ public CollectionOptions timeSeries (TimeSeriesOptions timeSeriesOptions ) {
286+
287+ Assert .notNull (timeSeriesOptions , "TimeSeriesOptions must not be null!" );
288+ return new CollectionOptions (size , maxDocuments , capped , collation , validationOptions , timeSeriesOptions );
256289 }
257290
258291 /**
@@ -303,6 +336,16 @@ public Optional<ValidationOptions> getValidationOptions() {
303336 return validationOptions .isEmpty () ? Optional .empty () : Optional .of (validationOptions );
304337 }
305338
339+ /**
340+ * Get the {@link TimeSeriesOptions} if available.
341+ *
342+ * @return {@link Optional#empty()} if not specified.
343+ * @since 3.3
344+ */
345+ public Optional <TimeSeriesOptions > getTimeSeriesOptions () {
346+ return Optional .ofNullable (timeSeriesOptions );
347+ }
348+
306349 /**
307350 * Encapsulation of ValidationOptions options.
308351 *
@@ -398,4 +441,87 @@ boolean isEmpty() {
398441 return !Optionals .isAnyPresent (getValidator (), getValidationAction (), getValidationLevel ());
399442 }
400443 }
444+
445+ /**
446+ * Options applicable to Time Series collections.
447+ *
448+ * @author Christoph Strobl
449+ * @since 3.3
450+ * @see <a href=
451+ * "https://docs.mongodb.com/manual/core/timeseries-collections">https://docs.mongodb.com/manual/core/timeseries-collections</a>
452+ */
453+ public static class TimeSeriesOptions {
454+
455+ private final String timeField ;
456+
457+ @ Nullable //
458+ private String metaField ;
459+
460+ private Granularity granularity ;
461+
462+ private TimeSeriesOptions (String timeField , @ Nullable String metaField , Granularity granularity ) {
463+
464+ this .timeField = timeField ;
465+ this .metaField = metaField ;
466+ this .granularity = granularity ;
467+ }
468+
469+ /**
470+ * Create a new instance of {@link TimeSeriesOptions} using the given field as its {@literal timeField}. The one,
471+ * that contains the date in each time series document. <br />
472+ * {@link Field#name() Annotated fieldnames} will be considered during the mapping process.
473+ *
474+ * @param timeField must not be {@literal null}.
475+ * @return new instance of {@link TimeSeriesOptions}.
476+ */
477+ public static TimeSeriesOptions timeSeries (String timeField ) {
478+ return new TimeSeriesOptions (timeField , null , Granularities .DEFAULT );
479+ }
480+
481+ /**
482+ * Set the name of the field which contains metadata in each time series document. Should not be the {@literal id}
483+ * nor {@link TimeSeriesOptions#timeSeries(String)} timeField} nor point to an {@literal array} or
484+ * {@link java.util.Collection}. <br />
485+ * {@link Field#name() Annotated fieldnames} will be considered during the mapping process.
486+ *
487+ * @param metaField must not be {@literal null}.
488+ * @return new instance of {@link TimeSeriesOptions}.
489+ */
490+ public TimeSeriesOptions metaField (String metaField ) {
491+ return new TimeSeriesOptions (timeField , metaField , granularity );
492+ }
493+
494+ /**
495+ * Select the {@link Granularity} parameter to define how data in the time series collection is organized. Select
496+ * one that is closest to the time span between incoming measurements.
497+ *
498+ * @return new instance of {@link TimeSeriesOptions}.
499+ */
500+ public TimeSeriesOptions granularity (Granularity granularity ) {
501+ return new TimeSeriesOptions (timeField , metaField , granularity );
502+ }
503+
504+ /**
505+ * @return never {@literal null}.
506+ */
507+ public String getTimeField () {
508+ return timeField ;
509+ }
510+
511+ /**
512+ * @return can be {@literal null}. Might be an {@literal empty} {@link String} as well, so maybe check via
513+ * {@link org.springframework.util.StringUtils#hasText(String)}.
514+ */
515+ @ Nullable
516+ public String getMetaField () {
517+ return metaField ;
518+ }
519+
520+ /**
521+ * @return never {@literal null}.
522+ */
523+ public Granularity getGranularity () {
524+ return granularity ;
525+ }
526+ }
401527}
0 commit comments