diff --git a/doctrine-mongo-mapping.xsd b/doctrine-mongo-mapping.xsd
index 5e7dd9f17..90d3c8fde 100644
--- a/doctrine-mongo-mapping.xsd
+++ b/doctrine-mongo-mapping.xsd
@@ -640,6 +640,8 @@
+
+
@@ -650,4 +652,11 @@
+
+
+
+
+
+
+
diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/TimeSeries.php b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/TimeSeries.php
index 6133ff09f..e4fe593eb 100644
--- a/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/TimeSeries.php
+++ b/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/TimeSeries.php
@@ -22,6 +22,8 @@ public function __construct(
public readonly ?string $metaField = null,
public readonly ?Granularity $granularity = null,
public readonly ?int $expireAfterSeconds = null,
+ public readonly ?int $bucketMaxSpanSeconds = null,
+ public readonly ?int $bucketRoundingSeconds = null,
) {
}
}
diff --git a/lib/Doctrine/ODM/MongoDB/SchemaManager.php b/lib/Doctrine/ODM/MongoDB/SchemaManager.php
index bd41c66a9..fb355705e 100644
--- a/lib/Doctrine/ODM/MongoDB/SchemaManager.php
+++ b/lib/Doctrine/ODM/MongoDB/SchemaManager.php
@@ -628,6 +628,8 @@ public function createDocumentCollection(string $documentName, ?int $maxTimeMs =
'metaField' => $class->timeSeriesOptions->metaField,
// ext-mongodb will automatically encode backed enums, so we can use the value directly here
'granularity' => $class->timeSeriesOptions->granularity,
+ 'bucketMaxSpanSeconds' => $class->timeSeriesOptions->bucketMaxSpanSeconds,
+ 'bucketRoundingSeconds' => $class->timeSeriesOptions->bucketRoundingSeconds,
],
static fn (mixed $value): bool => $value !== null,
);
diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php
index e278241b1..d909619de 100644
--- a/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php
+++ b/tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php
@@ -1027,6 +1027,35 @@ public function testTimeSeriesMappingWithExpireAfterSeconds(): void
self::assertSame(10, $metadata->timeSeriesOptions->expireAfterSeconds);
}
+
+ public function testTimeSeriesMappingWithBucketMaxSpanSeconds(): void
+ {
+ $metadata = $this->dm->getClassMetadata(TimeSeriesTestDocument::class);
+ $metadata->markAsTimeSeries(new ODM\TimeSeries('time', bucketMaxSpanSeconds: 10));
+
+ // We don't throw for invalid settings here, e.g. bucketMaxSpanSeconds not being equal to bucketRoundingSeconds
+ self::assertSame(10, $metadata->timeSeriesOptions->bucketMaxSpanSeconds);
+ }
+
+ public function testTimeSeriesMappingWithBucketRoundingSeconds(): void
+ {
+ $metadata = $this->dm->getClassMetadata(TimeSeriesTestDocument::class);
+ $metadata->markAsTimeSeries(new ODM\TimeSeries('time', bucketRoundingSeconds: 10));
+
+ // We don't throw for invalid settings here, e.g. bucketMaxSpanSeconds not being equal to bucketRoundingSeconds
+ self::assertSame(10, $metadata->timeSeriesOptions->bucketRoundingSeconds);
+ }
+
+ public function testTimeSeriesMappingWithGranularityAndBucketMaxSpanSeconds(): void
+ {
+ $metadata = $this->dm->getClassMetadata(TimeSeriesTestDocument::class);
+ $metadata->markAsTimeSeries(new ODM\TimeSeries('time', granularity: Granularity::Hours, bucketMaxSpanSeconds: 15, bucketRoundingSeconds: 20));
+
+ // We don't throw for invalid settings here, e.g. bucketMaxSpanSeconds not being equal to bucketRoundingSeconds
+ self::assertSame(Granularity::Hours, $metadata->timeSeriesOptions->granularity);
+ self::assertSame(15, $metadata->timeSeriesOptions->bucketMaxSpanSeconds);
+ self::assertSame(20, $metadata->timeSeriesOptions->bucketRoundingSeconds);
+ }
}
/** @template-extends DocumentRepository */