node.jsmongodbpymongottl

How to set different TTL for every document in MongoDB


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?


Solution

  • 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.