Docs Menu

Docs HomeDevelop ApplicationsMongoDB Manual

Time Series Collections

On this page

  • Procedures
  • Behavior

New in version 5.0.

Time series collections efficiently store sequences of measurements over a period of time. Time series data is any data that is collected over time and is uniquely identified by one or more unchanging parameters. The unchanging parameters that identify your time series data is generally your data source's metadata.

Example
Measurement
Metadata
Weather data
Temperature
Sensor identifier, location
Stock data
Stock price
Stock ticker, exchange
Website visitors
View count
URL

Compared to normal collections, storing time series data in time series collections improves query efficiency and reduces the disk usage for time series data and secondary indexes.

Note

You can only create time series collections on a system with featureCompatibilityVersion set to 5.0.

Before you can insert data into a time series collection, you must explicitly create the collection using either the db.createCollection() method or the create command:

db.createCollection(
"weather",
{
timeseries: {
timeField: "timestamp",
metaField: "metadata",
granularity: "hours"
}
}
)

When creating a time series collection, specify the following options:

Field
Type
Description
timeseries.timeField
string

Required. The name of the field which contains the date in each time series document. Documents in a time series collection must have a valid BSON date as the value for the timeField.

timeseries.metaField
string

Optional. The name of the field which contains metadata in each time series document. The metadata in the specified field should be data that is used to label a unique series of documents. The metadata should rarely, if ever, change.

The name of the specified field may not be _id or the same as the timeseries.timeField. The field can be of any type.

timeseries.granularity
string

Optional. Possible values are:

  • "seconds"

  • "minutes"

  • "hours"

By default, MongoDB sets the granularity to "seconds" for high-frequency ingestion.

Manually set the granularity parameter to improve performance by optimizing how data in the time series collection is stored internally. To select a value for granularity, choose the closest match to the time span between consecutive incoming measurements.

If you specify the timeseries.metaField, consider the time span between consecutive incoming measurements that have the same unique value for the metaField field. Measurements often have the same unique value for the metaField field if they come from the same source.

If you do not specify timeseries.metaField, consider the time span between all measurements that are inserted in the collection.

expireAfterSeconds
number
Optional. Enable the automatic deletion of documents in a time series collection by specifying the number of seconds after which documents expire. MongoDB deletes expired documents automatically. See Set up Automatic Removal for Time Series Collections (TTL) for more information.

Other options allowed with the timeseries option are:

  • storageEngine

  • indexOptionDefaults

  • collation

  • writeConcern

  • comment

Tip

See:

Each document you insert should contain a single measurement. To insert multiple documents at once, issue the following command:

db.weather.insertMany( [
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"temp": 12
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T04:00:00.000Z"),
"temp": 11
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T08:00:00.000Z"),
"temp": 11
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T12:00:00.000Z"),
"temp": 12
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T16:00:00.000Z"),
"temp": 16
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-18T20:00:00.000Z"),
"temp": 15
}, {
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T00:00:00.000Z"),
"temp": 13
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T04:00:00.000Z"),
"temp": 12
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T08:00:00.000Z"),
"temp": 11
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T12:00:00.000Z"),
"temp": 12
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T16:00:00.000Z"),
"temp": 17
},
{
"metadata": { "sensorId": 5578, "type": "temperature" },
"timestamp": ISODate("2021-05-19T20:00:00.000Z"),
"temp": 12
}
] )

To insert a single document, use the db.collection.insertOne() method.

To retrieve one document from a time series collection, issue the following command:

db.weather.findOne({
"timestamp": ISODate("2021-05-18T00:00:00.000Z")
})

For additional query functionality, use an aggregation pipeline such as:

db.weather.aggregate( [
{
$project: {
date: {
$dateToParts: { date: "$timestamp" }
},
temp: 1
}
},
{
$group: {
_id: {
date: {
year: "$date.year",
month: "$date.month",
day: "$date.day"
}
},
avgTmp: { $avg: "$temp" }
}
}
] )

The example aggregation pipeline groups all documents by the date of the measurement and then returns the average of all temperature measurements that day:

{
"_id" : {
"date" : {
"year" : 2021,
"month" : 5,
"day" : 18
}
},
"avgTmp" : 12.714285714285714
}
{
"_id" : {
"date" : {
"year" : 2021,
"month" : 5,
"day" : 19
}
},
"avgTmp" : 13
}

To determine if a collection is of type time series, use the listCollections command:

db.runCommand( { listCollections: 1.0 } )

If the collection is a time series collection, it returns this:

{
cursor: {
id: <number>,
ns: 'test.$cmd.listCollections',
firstBatch: [
{
name: <string>,
type: 'timeseries',
options: {
expireAfterSeconds: <number>,
timeseries: { ... }
},
...
},
...
]
}
}

Time series collections behave like normal collections. You can insert and query your data as you normally would. MongoDB treats time series collections as writable non-materialized views on internal collections that automatically organize time series data into an optimized storage format on insert.

When you query time series collections, you operate on one document per measurement. Queries on time series collections take advantage of the optimized internal storage format and return results faster.

The implementation of time series collections uses internal collections that reduce disk usage and improve query efficiency. Time series collections automatically order and index data by time. The internal index for a time series collection is not displayed by listIndexes.

Tip

To improve query performance, you can manually add secondary indexes on the fields specified as the metaField and the timeField.

Time series collections ignore the global default compression algorithm, snappy, in favor of zstd, unless a different compression algorithm is specified using the storageEngine option when the collection was created. For example, to change the compression algorithm to snappy for a new weather collection, add the following option:

db.createCollection(
"weather",
{
timeseries: {
timeField: "timestamp"
},
storageEngine: {
wiredTiger: {
configString: "block_compressor=snappy"
}
}
}
)

Valid block_compressor options are:

  • snappy

  • zlib

  • zstd (default)

  • none

Starting in MongoDB 5.2, time series collection data is further compressed to save database space. This compression does not affect query results, nor does it negatively affect performance.

←  Capped CollectionsTime Series Collection Limitations →

On this page