Search code examples
mongodbmongoose

Mongoose - how to expire/delete a subdocument?


Im trying to expire a subdocument after 30 seconds. Anything I tried so far doesnt do anything.

What I tried:

const productSchema = new mongoose.Schema({
    name: { 
        type: String
    },
    reports: [ReportSchema]
})

mongoose.model('Product', productSchema);

const reportSchema = new mongoose.Schema({   
    title: {
        type: String,
    },
    createdAt: { 
        type: Date,
        expires: 30
    },
});

also tried:

const reportSchema = new mongoose.Schema({   
    title: {
        type: String,
    },
    createdAt: { type: Date,  expires: 30 }
});

also tried:

reportSchema.index({ createdAt: 1 }, { expireAfterSeconds: 30 });

Solution

  • TTL index is an index. Expiration time applies to the whole document in reportSchema collection but it won't update any related documents.

    You need to keep reportSchema on separate collection to benefit from the TTL index, use references in productSchema instead of embedding them. Please read about referencing in https://mongoosejs.com/docs/populate.html

    As a side note, the eraser kicks in every minute, so you may still see documents remain in the collection after 30 sec.

    UPDATE

    There is no built-in functionality to remove subdocuments. You need to implement own "expirator" - a cron job, a daemon, or any other mean to periodically run something like this query:

    db.products.update({
      "reports.createdAt": {
        $lte: new Date()
      }
    },
    {
      "$pull": {
        "reports": {
          "createdAt": {
            $lte: new Date()
          }
        }
      }
    },
    {
      "multi": true
    })