Best practices for computed values in Meteor? (document and collection level)


#1

Say you have a Person collection with models that look this:

{
  name: "Bob",
  age: 24,
  gender: "Male",
  start_date: ISODate("2014-01-30T06:01:17.171Z")
  salary: 80000
}

You want to store some calculated fields - some of them are at the document level - e.g. days_in_service might be the number of days since start_date (maybe not the best example, since it changes, but you get the idea) , or monthly_salary might be salary dvided by 12.

Some of them are at the collection level - e.g. percentage_males is the percentage of people that are male, or average_salary is the average salary across the collection.

What is the best way of handling these things in Meteor?

Coming from Django, there are a few ways to handle computed fields.

For instance-level things, you can make them model properties (using @), so that you can access them as a normal attribute of a model, but they’ll be calculated each time you access them.

Or you can store them as actual fields along with each model, and use signals to keep them updated.

What would be the equivalent to these in Meteor?

For example, how would you best create a dynamic field that was calculated each time?

Or if you wanted to actually store it as a new field - how would you create it so that it was reactive, like other fields in Meteor? So that for example, if you updated a person’s salary, their monthly_salary field would also automatically be updated?

Or if it was a collection-level thing and you had the averages stored in another collection - if you added a new person, how would you ensure the averages got updated?


#2

For dynamic (non stored) fields use: https://atmospherejs.com/dburles/collection-helpers
For stored computed fields use a before insert/update hook with: https://atmospherejs.com/matb33/collection-hooks

Meteor will take care of the reactivity for you.


#3

Thanks! =). I’ll check out both of those packages.

They look like they’ll take care of the document-level stuff easily (either dynamic or persisted, as you said). For collection level (e.g. calculated value for the overall Person collection) - I suppose the collection-hooks will still work, but do you have any tips for how to do it dynamically? (I assume collection-helpers won’t work here, unless there’s something I’m missing).

Hmm, wondering why this sort of stuff isn’t in Meteor core? It seems like pretty common functionality in a web framework - or is it stuff they’re hoping to eventually migrate into Meteor core?

Also - any caveats you’ve found using either of these, or major gotchas I should be aware of?


#4

When you say at the collection level it seems you mean a reactive aggregate. Meteor doesn’t support that our of the box but you can make your own. Let me know if this is what you mean.

The packages are top notch so you won’t find many surprises. I just did a Screencast on collection hooks: meteorcasts.net


#5

Yup, you’re spot on, reactive aggregates are what I mean. (Basically this - https://docs.djangoproject.com/en/1.8/topics/db/aggregation/ - but for Meteor - and keen to compare both dynamic and persisted, to see what fits).

I think I’m leaning towards collection-hooks for my use-case, as I’m willing to trade-off increased MongoDB storage for not having to re-calculate it each time it’s accessed.

Thanks for making the video as well. Is this a regular series you’re making now?