JavaScript Object vs minimongo efficiency

154 Views Asked by At

My Meteor client receives data from the server and stores it in minimongo. This data is guaranteed not to change during their session, so I don't need Meteor's reactivity. The static data just happens to arrive by that route; let's just take that as a given.

The data looks like this:

{_id: 'abc...', val: {...}}

On the client, is it more efficient for me to look up values using:

val_I_need = Collection.findOne({id})

or to create a JavaScript object:

data = {}
Collection.find().fetch().map((x) => {data[x._id] = x.val})

and use it for look ups:

val_I_need = data[id]

Is there a tipping point, either in terms of the size of the data or the number of look ups, where the more efficient method changes, or outweighs the initial cost of building the object?

2

There are 2 best solutions below

0
On BEST ANSWER

FindOne may be more efficient on larger datasets because it looks up using cursors where _id is an indexed key while your find().fetch() approach requires to get all docs and then iterate manually by mapping.

Note, that findOne could also be replaced by .find({_id:desiredId}).fetch()[0](assuming it returns the desired doc).

More on this in the mongo documentation on query performance.

However, if it concerns only one object that is afterwards not reactively tracked, I would rather load it via a "findOne"-returning method from the server:

export const getOne = new ValidatedMethod({
    name: "getOne",
    validate(query) {
        // validate query schema
        // ...
    },
    run(query) {

        // CHECK PERMISSIONS
        // ...

        return MyCollection.findOne(query);
});

This avoids using publications / subscriptions and thus minimongo for this collection on the current client template. Think about that pub/sub has already some reactivity initialized to observe the collection and thus eats up some computation somewhere.

0
On

My gut feeling is that you'll never hit a point where the performance gain of putting it in an object makes a noticeable difference.

It's more likely that your bottleneck will be in the pub/sub mechanism, as it can take a while to send all documents to the client.

You'll see a much more noticeable difference for a large dataset by retrieving the data using a Meteor method.

At which point you've got it in a plain old javascript object anyway and so end up with the small performance gain of native object lookups as well.