I fear I may have included too many issues in one post, so slimming this question down. Really hoping someone can help as this is stopping me cold. Thank you.
This is what I am trying to accomplish.
- On click, user inserts new document in Valuations collection
- User then adds company tickers through input (array saved in
valuationSelections
field of Valuations document)
For each Valuation, I need to
- aggregate data across those companies from the Companies collection whose value for
ticker
is invaluationSelections
. No user edits are made directly to Companies collection.valuationSelections
can contain similar companies across instances - observe
Valuations
collection for changes and update the aggregation
The code below returns the correct values on the server, however:
- Since $out will clean out the collection before adding the new results (which doesn’t help for multiple aggregations), how can I instead copy
results
to a document in the Valuation collection? - I’ve tried to replicate @levid’s great publication example in this post to take advantage of the reactivity. Can I call a method within a publication, or vice versa?
Guidance on any part would be greatly appreciated.
packages
meteorhacks:aggregate
server/methods.js
Meteor.methods({
valuationAggregate: function(valuationId, valuationSelections) {
//Aggregate and publish average of company valuation data for a user-selected series of companies./
//Selections are saved in Valuations collection for reference and data for aggregation comes from Companies collection.//
check(valuationId, String);
check(valuationSelections, Array);
var pipelineSelections = [
//Match documents in Companies collection where the 'ticker' value was selected by the user.//
{$match: {ticker: {$in: valuationSelections}}},
{
$group: {
_id: null,
avgEvRevenueLtm: {$avg: {$divide: ["$capTable.enterpriseValue", "$financial.ltm.revenue"]}},
avgEvRevenueFy1: {$avg: {$divide: ["$capTable.enterpriseValue", "$financial.fy1.revenue"]}},
avgEvRevenueFy2: {$avg: {$divide: ["$capTable.enterpriseValue", "$financial.fy2.revenue"]}},
avgEvEbitdaLtm: {$avg: {$divide: ["$capTable.enterpriseValue", "$financial.ltm.ebitda"]}},
//more//
}
},
{
$project: {
_id: 0,
resultsId: {$literal: valuationId},
avgEvRevenueLtm: 1,
avgEvRevenueFy1: 1,
avgEvRevenueFy2: 1,
avgEvEbitdaLtm: 1,
//more//
}
}
];
var results = Companies.aggregate(pipelineSelections);
console.log(results);
}
});
client/templates/valuationCalc.js
Template.ValuationCalc.events({
'click .submit': function(e) {
e.preventDefault();
//Get id of Valuation to use in new collection of results.//
var valuationId = this._id;
console.log(valuationId);
//Identify user selections//
var valuationSelections = this.valuationSelections;
console.log(valuationSelections);
Meteor.call('valuationAggregate', valuationId, valuationSelections, function () {
});
}
});
Returns on the server
I20150924-15:44:51.902(-4)? avgEvRevenueLtm: 3.988137239679733,
I20150924-15:44:51.902(-4)? avgEvRevenueFy1: 3.8159564713187155,
I20150924-15:44:51.902(-4)? avgEvRevenueFy2: 3.50111769838031,
I20150924-15:44:51.902(-4)? avgEvEbitdaLtm: 11.176476895728268
//more//
I20150924-15:44:51.903(-4)? valuationId: 'Qg4EwpfJ5uPXyxe62' } ]