Jessica
Jessica

Reputation: 9830

Mongo DB document is not deleting after it expires

I'm trying to set up a model so that when a table get added, it will have an expiration date, after it expires, the table will delete itself. I tried implementing it like this:

expires: '1m'

and with

expires: 10

I have a table set up like the following:

const verifySchema = new mongoose.Schema({
    _userId: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
        ref: 'User'
    },
    hash: { type: String, required: true },
    createdAt: { type: Date, required: true, default: Date.now, expires: '1m' }
});

The problem is, nothing happens after the minute. It doesn't get deleted in the database. Am I doing anything wrong?

How can I delete a table after a minute?

Upvotes: 2

Views: 2240

Answers (1)

t.888
t.888

Reputation: 3902

Here's a working sample using mongoose v5.5.9. It turns out the missing part is the schema entry index: { expires: '1m' } in the createdAt field.

const mongoose = require('mongoose')
// $ npm install uuid
const uuid = require('uuid')

const ObjectId = mongoose.Types.ObjectId

// Avoid deprecation warnings
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);

// Create the schema.
const verifySchema = new mongoose.Schema({
  _userId: {
      type: ObjectId,
      required: true,
      ref: 'User'
  },

  hash: { type: String, required: true },

  createdAt: {
    type: Date,
    required: true,
    default: Date.now,
    index: { expires: '1m' }
  }
},
{
  collection: 'verify'
});

// Connect to mongodb.
mongoose.connect('mongodb://localhost/test').then(() => {
  // Create the model
  const Verify = mongoose.model('Verify', verifySchema)

  // Create a model instance.
  const v = new Verify({
    _userId: new ObjectId(),
    hash: uuid.v4()
  })

  // Save the model.
  v.save().then(() => {
    // Close the connection.
    mongoose.connection.close()
  })
})

You can check your indexes with MongoDB Compass, or using the shell:

> use test
> db.verify.getIndexes()

Look for the field value expireAfterSeconds which will indicate the TTL time in seconds that is set for the index. In order to change the TTL, you will need to drop the index on createdAt. In the shell, the command would be db.verify.dropIndex(<index_name>) or db.verify.dropIndexes() to drop all indexes on the collection.

For upserting documents, such as with findOneAndUpdate, you will need to pass setDefaultsOnInsert: true to the options like so:

// Connect to mongodb.
mongoose.connect('mongodb://localhost/test').then(() => {
  // Create the model
  const Verify = mongoose.model('Verify', verifySchema)

  const _userId = new ObjectId()
  const hash = uuid.v4()
  const options = { upsert: true, setDefaultsOnInsert: true }

  // Upsert the document.
  Verify.findOneAndUpdate( { _userId }, { hash }, options).then(() => {
    mongoose.connection.close()
  })
})

This is necessary or else the createdAt field, which contains the TTL index, won't get added to the document.

Upvotes: 4

Related Questions