While using Change Stream in MongoDB with Socket.io, the on 'change' is getting triggered multiple times

Viewed 1017

I have been trying to catch any realtime update or insert in the mongodb and using socket.io to change information accordingly on the next page. But whenever there is any update in the database, the on 'change' stream is getting triggered multiple times. I assume that this might also be the reason behind the socket acting slow and with delay. Any kind of help is really appreciated.

const Order = new mongoose.model("Order", orderSchema);

io.on('connection', function(socket){
    console.log(socket.id);
    Order.watch([{ $match: {operationType: {$in: ['insert']}}}]).
    on('change', data => {
        console.log('Insert action triggered'); //getting triggered thrice
        console.log(new Date(), data.fullDocument);
        socket.emit("changes", data.fullDocument); 

    });
    Order.watch([{ $match: {operationType: {$in: ['update']}}}]).
    on('change', data => {
        console.log('Update action triggered'); //getting triggered thrice
        console.log(new Date(), data.updateDescription.updatedFields);
        socket.emit("customer", data);
    });

});
2 Answers

You need to put your mongodb changeStreams outside the io.on('connection') and use io.emit() instead of socket.emit()

Here is the code for example:

const Order = new mongoose.model("Order", orderSchema);

io.on('connection', function(socket){
    console.log(socket.id);

    socket.on('disconnect', (reason) => {
        console.log(reason);
    });
});

Order.watch([{ $match: {operationType: {$in: ['insert']}}}]).
on('change', data => {
    console.log('Insert action triggered');
    console.log(new Date(), data.fullDocument);
    io.emit("changes", data.fullDocument); 

});
Order.watch([{ $match: {operationType: {$in: ['update']}}}]).
on('change', data => {
    console.log('Update action triggered');
    console.log(new Date(), data.updateDescription.updatedFields);
    io.emit("customer", data);
});

@swati sinha answer works for me but I also want to use change stream and socket to be in separate function so that's why I make a little tweak

const Order = new mongoose.model("Order", orderSchema);

let OrderStream = Order.watch([{ $match: {operationType: {$in: ['insert']}}}])

io.on('connection', function(socket){
    console.log(socket.id);

    OrderStream.on('change',function(change){
        socket.emit('changes',change)
    })

    socket.on('disconnect', (reason) => {
        console.log(reason);
    });
});
 
Related