Skip to content

Allow creating time series collections with custom name and CollectionOptions derived from annotation #4684

Open
@gbaso

Description

@gbaso

According to the documentation, it is possible to create a time series collection via MongoTemplate by either providing explicit CollectionOptions or a class annotated with @TimeSeries:

@TimeSeries(timeField = "timestamp")
record MyTimeSeries(@Id String id, Instant timestamp, String value) {}

mongoTemplate.createCollection(MyTimeSeries.class)

in which case the CollectionOptions are derived from the annotation:

if (entity.isAnnotationPresent(TimeSeries.class)) {
TimeSeries timeSeries = entity.getRequiredAnnotation(TimeSeries.class);
if (entity.getPersistentProperty(timeSeries.timeField()) == null) {
throw new MappingException(String.format("Time series field '%s' does not exist in type %s",
timeSeries.timeField(), entity.getName()));
}
TimeSeriesOptions options = TimeSeriesOptions.timeSeries(timeSeries.timeField());
if (StringUtils.hasText(timeSeries.metaField())) {
if (entity.getPersistentProperty(timeSeries.metaField()) == null) {
throw new MappingException(
String.format("Meta field '%s' does not exist in type %s", timeSeries.metaField(), entity.getName()));
}
options = options.metaField(timeSeries.metaField());
}
if (!Granularity.DEFAULT.equals(timeSeries.granularity())) {
options = options.granularity(timeSeries.granularity());
}
collectionOptions = collectionOptions.timeSeries(options);
}

However, if you want to create the collection with a custom name (not derived from the class), there is currently no option for deriving the CollectionOptions from the annotation. The only overloads of mongoTemplate.createCollection that take a String collectionName also require explicit CollectionOptions.

Using mongoTemplate.save(value, "myCustomName") is a non-starter since it does not read the entity metadata and just creates a basic collection (not a time series) with no other options.

Custom names are important for several widespread use cases, for example collection-level multi-tenancy, where you would create multiple collection with the same definition to segregate data for different tenants, or any other types of data segmentation.

I propose new methods to create a collection that take both the collectionName and the entityClass as inputs:

	public <T> MongoCollection<Document> createCollection(String collectionName, Class<T> entityClass) {
		return createCollection(collectionName, entityClass,
				operations.forType(entityClass).getCollectionOptions());
	}

	public <T> MongoCollection<Document> createCollection(String collectionName, Class<T> entityClass,
			@Nullable CollectionOptions collectionOptions) {
		Assert.notNull(collectionName, "CollectionName must not be null");
		Assert.notNull(entityClass, "EntityClass must not be null");
		return doCreateCollection(collectionName,
				operations.convertToCreateCollectionOptions(collectionOptions, entityClass));
	}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions