Least intensive way to detect when mongo collection has changed?

I need to know when a collection has been changed in any way (document added,updated or removed). I don’t need to know what exactly has changed, just that a change has happened.

I’ve tried using for example

Collection.find().observe({
added: function(document){
    console.log('doc added');
},
changed:function(new_document, old_document){
        console.log('doc changed');
},
removed:function(document){
        console.log('doc removed');
}
});

The issue with this is that a significant (6.25%) CPU spike occurs every 30 seconds or so for a second or 2 on a collection of 2000 documents which is not ideal. This is on a 6700K CPU.

Any easy/neat way to do this? At the moment I’ve implemented a non-elegant solution of calling a function every time the collection is changed but this results in me having to call the function in 40+ places all over the application.

Sure I could go through and redo all my code so that the collection is only changed at a singular point, but before I do that I’m wondering if there is a better way.

I presume you’re talking about the server?

Are you using oplog? Search this forum for “oplog” and “performance”/“CPU” and you might find some useful posts, including one of mine.

Rather then observing the collection, try collection-hooks so you can automatically define a function to be called after any insert/update/remove command.

2 Likes

@wildhart’s suggestion, collection-hooks, should work very well but only if you are certain that the collection is always updated from within Meteor.

If you have services that update it from outside, and/or for low overhead, just use this NPM package: https://www.npmjs.com/package/mongo-oplog

We use it in production for a use case similar to yours.

1 Like

Ok thank you I’ll take a look at hooks

You could also do the same thing that they do in the todo sample app, extend Mongo.Collection. Again, will only work if this the db isn’t being updated externally:

 import { Mongo } from 'meteor/mongo';

class TodosCollection extends Mongo.Collection {
  insert(doc, callback) {
    const result = super.insert(doc, callback);
    // log change
    return result;
  }

  update(selector, modifier) {
    const result = super.update(selector, modifier);
    // log change
    return result;
  }

  remove(selector) {
    const result = super.remove(selector);
    // log change
    return result;
  }
}