As far I know, currently MongoDB TTL are managed by expireAfterSeconds
index and it's setting for all documents inside a collection.
Is there any built-in way to set expiration to single document?
As far I know, currently MongoDB TTL are managed by expireAfterSeconds
index and it's setting for all documents inside a collection.
Is there any built-in way to set expiration to single document?
On each documet you can set a field of expires
and create the following index:
db.docs.createIndex( { expires:1 }, {expireAfterSeconds: 0 } );
documents inside this collection will get removed once time ticks over the expired field. However, this may take up 60 seconds as the background task that runs to remove documents runs every 60 seconds.
Here's an example though...
So let's insert a bunch of documents adding 60 seconds to each document each time we add them.
> var expires = new Date(); // Gets the current datetime.
> expires.setSeconds(expires.getSeconds() + 60)
1587812623023
> db.docs.insert({expires})
WriteResult({ "nInserted" : 1 })
> expires.setSeconds(expires.getSeconds() + 60)
1587812683023
> db.docs.insert({expires})
WriteResult({ "nInserted" : 1 })
> expires.setSeconds(expires.getSeconds() + 60)
1587812743023
> db.docs.insert({expires})
WriteResult({ "nInserted" : 1 })
> db.docs.find()
{ "_id" : ObjectId("5ea418de00f07c4d6461090b"), "expires" : ISODate("2020-04-25T11:03:43.023Z") }
{ "_id" : ObjectId("5ea418e300f07c4d6461090c"), "expires" : ISODate("2020-04-25T11:04:43.023Z") }
{ "_id" : ObjectId("5ea418e600f07c4d6461090d"), "expires" : ISODate("2020-04-25T11:05:43.023Z") }
Now if we add the TTL index.
db.docs.createIndex( { expires:1 }, { expireAfterSeconds: 0 } )
Then we can monitor our collection each 60 seconds and see each document getting removed.
> new Date()
ISODate("2020-04-25T11:03:28.278Z")
> db.docs.find()
{ "_id" : ObjectId("5ea418de00f07c4d6461090b"), "expires" : ISODate("2020-04-25T11:03:43.023Z") }
{ "_id" : ObjectId("5ea418e300f07c4d6461090c"), "expires" : ISODate("2020-04-25T11:04:43.023Z") }
{ "_id" : ObjectId("5ea418e600f07c4d6461090d"), "expires" : ISODate("2020-04-25T11:05:43.023Z") }
Nothing has been removed yet.
> new Date()
ISODate("2020-04-25T11:04:18.652Z")
> db.docs.find()
{ "_id" : ObjectId("5ea418e300f07c4d6461090c"), "expires" : ISODate("2020-04-25T11:04:43.023Z") }
{ "_id" : ObjectId("5ea418e600f07c4d6461090d"), "expires" : ISODate("2020-04-25T11:05:43.023Z") }
One document has gone.
> new Date()
ISODate("2020-04-25T11:05:17.705Z")
> db.docs.find()
{ "_id" : ObjectId("5ea418e600f07c4d6461090d"), "expires" : ISODate("2020-04-25T11:05:43.023Z") }
Another is gone.
> new Date()
ISODate("2020-04-25T11:06:31.390Z")
> db.docs.find()
>
and we're left with no doucments in our collection.
expireAfterSeconds
must be set to 1. If you set it to 0 it will default to disabling TTL expiration. –
Mylohyoid expireAfterSeconds
on the index is the time it'll wait after the datetime of the field specified, because we set 0
it will expire at the datetime field. This is all also done on a background thread which reads the values of the index then deletes them when expired. –
Westphal Since this is the top search result for "different TTL for every document in pymongo", I'll post this answer here.
One important thing to make documents in the same collection expire at different points in time is to use datetime with the same timezone as whatever timezone your MongoDB instance is running in. This is not a problem in node.js because new Date()
returns datetime in UTC.
In my case, I was using the naïve datetime (in Python) but my MongoDB instance was in UTC, so all documents were getting deleted in one go. Using a datetime in UTC fixed the issue.
The following is an example code where every document expires after 60 seconds .
from datetime import datetime, UTC
# create the ttl index
collection.create_index(keys="created_at", expireAfterSeconds=60)
# insert a doc
collection.insert_one({"created_at": datetime.now(UTC)})
© 2022 - 2024 — McMap. All rights reserved.