Skip to content

Commit 889096c

Browse files
committed
Improvements of doc and tests related with recent timeseries collection support
1 parent 64c28ef commit 889096c

File tree

4 files changed

+33
-32
lines changed

4 files changed

+33
-32
lines changed

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Development
99
- (Fill this out as you fix issues and develop your features).
1010
- Allow gt/gte/lt/lte/ne operators to be used with a list as value on ListField #2813
1111
- Switch tox to use pytest instead of legacy `python setup.py test` #2804
12+
- Add support for timeseries collection #2661
1213

1314
Changes in 0.28.2
1415
=================

docs/guide/defining-documents.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,26 @@ The following example shows a :class:`Log` document that will be limited to
491491
ip_address = StringField()
492492
meta = {'max_documents': 1000, 'max_size': 2000000}
493493

494+
Timeseries collections
495+
------------------
496+
A :class:`~mongoengine.Document` may use a **Timeseries Collection** by specifying
497+
:attr:`timeseries` in the :attr:`meta` dictionary. Timeseries collection were added
498+
in MongoDB 5.0 (`doc <https://www.mongodb.com/docs/v5.3/core/timeseries-collections/>`_).
499+
The following example shows a Document class with a basic setup::
500+
501+
class SensorData(Document):
502+
timestamp = DateTimeField(required=True)
503+
temperature = FloatField()
504+
505+
meta = {
506+
"timeseries": {
507+
"timeField": "timestamp",
508+
"metaField": "temperature",
509+
"granularity": "seconds",
510+
"expireAfterSeconds": 5,
511+
},
512+
}
513+
494514
.. defining-indexes_
495515
496516
Indexes

tests/document/test_timeseries_collection.py

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import time
12
import unittest
23
from datetime import datetime, timedelta
34

@@ -102,9 +103,7 @@ def test_timeseries_expiration(self):
102103
assert collection.count_documents({}) == 1
103104

104105
# Wait for more than the expiration time
105-
import time
106-
107-
time.sleep(3)
106+
time.sleep(2)
108107
assert collection.count_documents({}) > 0
109108

110109
@requires_mongodb_gte_50
@@ -135,12 +134,8 @@ class SensorDataWithIndex(Document):
135134

136135
indexes = collection.index_information()
137136

138-
assert (
139-
"timestamp_index" in indexes
140-
), "Index on 'timestamp' field was not created"
141-
assert (
142-
"temperature_index" in indexes
143-
), "Index on 'temperature' field was not created"
137+
assert "timestamp_index" in indexes
138+
assert "temperature_index" in indexes
144139

145140
@requires_mongodb_gte_50
146141
def test_timeseries_data_insertion_order(self):
@@ -158,9 +153,9 @@ def test_timeseries_data_insertion_order(self):
158153

159154
# Check the insertion order
160155
assert len(documents) == 3
161-
assert documents[0].temperature == 22.0 # Earliest document
162-
assert documents[1].temperature == 23.4 # Middle document
163-
assert documents[2].temperature == 24.0 # Latest document
156+
assert documents[0].temperature == 22.0
157+
assert documents[1].temperature == 23.4
158+
assert documents[2].temperature == 24.0
164159

165160
@requires_mongodb_gte_50
166161
def test_timeseries_query_by_time_range(self):
@@ -182,21 +177,6 @@ def test_timeseries_query_by_time_range(self):
182177
assert documents[0].temperature == 23.0
183178
assert documents[1].temperature == 24.0
184179

185-
@requires_mongodb_gte_50
186-
def test_timeseries_large_data_volume(self):
187-
"""Ensure that the time-series collection can handle a large volume of data insertion."""
188-
189-
self.SensorData._get_collection_name()
190-
collection = self.SensorData._get_collection()
191-
192-
for i in range(10000):
193-
self.SensorData(
194-
timestamp=datetime.utcnow() - timedelta(seconds=i),
195-
temperature=20.0 + i % 5,
196-
).save()
197-
198-
assert collection.count_documents({}) == 10000
199-
200180

201181
if __name__ == "__main__":
202182
unittest.main()

tests/utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import functools
12
import operator
23
import unittest
34

@@ -77,14 +78,13 @@ def requires_mongodb_gte_36(func):
7778
:param oper: The operator to apply (e.g. operator.ge)
7879
"""
7980

81+
@functools.wraps(func)
8082
def _inner(*args, **kwargs):
8183
mongodb_v = get_mongodb_version()
8284
if oper(mongodb_v, mongo_version_req):
8385
return func(*args, **kwargs)
86+
else:
87+
pretty_version = ".".join(str(n) for n in mongo_version_req)
88+
pytest.skip(f"Needs MongoDB {oper.__name__} v{pretty_version}")
8489

85-
pretty_version = ".".join(str(n) for n in mongo_version_req)
86-
pytest.skip(f"Needs MongoDB {oper.__name__} v{pretty_version}")
87-
88-
_inner.__name__ = func.__name__
89-
_inner.__doc__ = func.__doc__
9090
return _inner

0 commit comments

Comments
 (0)