Search code examples
mongodbmongoosettl

MongoDB, Mongoose delete element after x time and receive event


I have an expressjs api which uses mongoose to manage the MongoDB. Now I have a document called notifications, some users receive notifications when some conditions are met, e.g. new item(s) are available for the user. The notifications are only sent in x time (stored in user settings) and every user can have max 1 notification in the notification collection. After a notification is sent it is deleted.

I can ofcourse retrieve every x time all user settings of users that have a notification. And then check (time comparison) which users can be notified now.

I would like to delete a notification after x time and then receive a delete event, and then I can send a notification based on that event.


Solution

  • What I did was to create another collection e.g. NotificationTtl. A NotificationTtl is only created when a Notification is created, with the ttl set to the correctly based on the user settings.

    We make another collection because it is better not to delete the notification before it has been sent. We can add a field with notificaiton_id, but because every notification has one notificationttl we can give the notificationttl the same id as the notification.

    var NotificationTtlSchema = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
    
    var NotificationTtl = mongoose.model('NotificationTtl', NotificationTtlSchema);
    NotificationTtl.watch().
        on('change', data => { 
            //this will be called ever time create/update/delete executes here we can listen for delete 
    });
    

    In the watch we can then listen for a delete operation if the delete operation has been executed we can get the id of the notificationttl and with that id we can retrieve the notification and send it, after it has been send we can delete it.

    This all works only if the mongodb is a replicaset and a master node, else the watch functionality wont work.

    So what happens now is that everytime the notifiction ttl expires I will get an event in my watch. The event will have operationType called delete, I will then retrieve the correct notification and send it to the user.