Meteor subscription to the last 20min records


#1

Hi everybody!
I’m working with meteor and react.
I’m building a real-time trend chart.
The real time chart should shows the lasts 20 minutes, and must keep moving forward with the actual time.

I have imagined that the solution to this problem should be something like update the subscription parameters each second, maybe through a setInterval:

pseudo-code:


setInterval(
  Meteor.subscribe('temperature', {gte: new Date()-20minutes, lt: new Date()}),
  1000
)

output @12:00 (from 11:40 to 12:00):

> {_id: ..., date: 2018-05-24 12:00:00, temperature: 20.0}
   {_id: ..., date: 2018-05-24 11:55:00, temperature: 20.0}
   {_id: ..., date: 2018-05-24 11:50:00, temperature: 21.0}
   {_id: ..., date: 2018-05-24 11:45:00, temperature: 23.0}

Another solution I’ve worked out is to subscribe to the last inserted document and pass its ‘date’ as upper-bound to the subscription (through an HOC):

class ChartComp extends Component {
...
}

ChartCompContainer = withTracker((props) => {
  var gte = props.upperBound-20mins
  var lt  = props.upperBound
  Meteor.subscribe('temperature', {gte: gte, lt: lt})

  return {
    temps: Temperature.find({}, {sort: {date: -1}}).fetch()
  }
}
})(ChartComp)

export default ChartCompContainerContainer = withTracker((props) => {
  Meteor.subscribe('lastTemperatureInserted')
  return {
    upperBound: Temperature.findOne({}, {sort: {date: -1}}).fetch()
  }
}
})(ChartCompContainer)

in this way, as soon as a new document will be inserted, a new upperBound value is sent through props and the temperature subscription parameters updates to the last document inserted.

Can you find out a better solution? Which one is the best between the previous two?

Thankyou for your help!


#2

For a simple solution can you just subscribe with limit to last 4 results (or however many you expect in the 20 min time interval)? In your example when a new record is inserted at 12.05, your result set will update to show record from 11.50 as last entry. Then you don’t need to change the subscription.


#3

Hello @globalise! Thank you for your answer!

Yeah, your solution seems to be neat. I haven’t considered it because if I don’t have entries for a while, the chart remains stucked at the last entry. Anyway in my case this problem should not heppen, because all the values are continuosly sampled on a fixed and well known time base.

In a general case, what do you think of the nesting of HOC? Is that a good practice or it could brings side effects?


#4

The most robust way to model this is to represent the entire chart with a single document, where each key is an x value on your chart and the value is the y value on your chart. The _id should refer to which chart on your site this particular data renders for. For example:

let chart = {
   _id: 'realtime-temperature-chart-last-20-minutes',
   '2018-05-24 11:55:00': 20.0,
   '2018-05-24 12:00:00': 20.0,
   '2018-05-24 11:50:00': 21.0,
   '2018-05-24 11:45:00': 23.0
}

I would suggest making a Charts collection, if you use a lot of these charts, that each correspond to the chart you need.

On the server, set a timer that updates the database entry for 'realtime-temperature-chart-last-20-minutes', removing old keys and introducing new ones in exactly the way you intend to render it. For example,

Meteor.setInterval(() => {
  let realtimeTempChartLast20 = { /* compute a new chart */ };
  Charts.update('realtime-temperature-chart-last-20-minutes', realtimeTempChartLast20);
}, 20*60*1000);

To get the data, don’t overthink it:

// on server
Meteor.publish('charts', () => {
  return Charts.find()
});

// on client
Meteor.subscribe('charts');

This model will be the absolute least error prone, easiest to maintain, most flexible and most synergistic with the way Meteor’s live DDP model actually works.


#5

Ok, thank you for your answer.
I’ve worked on it for few hours this weekend.
I’ve moved on the db schema suggested by you, splitting charts by year, for avoiding to reach the max document size.
I’ve implemented also your real time solution, which has been a bit tricky to realize: I had got to implement a server side method for updating the time span, which must be changable from the client side.
Anyway thank you for your suggestion, it’s neat and straightforward.