使用Meteor.js在发布到客户端之前重新采样时间数据

时间:2014-07-04 01:19:47

标签: javascript jquery node.js time meteor

集合data包含时间序列数据,例如

[
    { timestamp: 1404436523578, distance: 400 }, 
    { timestamp: 1404436525123, distance: 401 },
    { timestamp: 1404436578372, distance: 402 },
    { timestamp: 1404436382736, distance: 403 },
]

此数据集必须使用代表10分钟间隔的数据点进行绘制。

在发布重采样数据之前,如何在客户端浏览器上执行重新采样,而不是将大数据集发布到客户端浏览器,我们如何在服务器端重新采样数据呢?

是否有任何插件/软件包可以帮助重新采样时间序列数据?我只能找到one for Python

2 个答案:

答案 0 :(得分:4)

您可以使用自定义发布。查看counts-by-room示例。

基本模式:

服务器端

Meteor.publish('resampledData', function() {

  var self = this;

  var data = getActualData();
  var resampledData = ABRACADABRA(data);

  _.each(resampledData, function(point){
    self.added('resampledData', point._id, point);
  });

  self.ready();

});

客户端

ResampledData = new Meteor.Collection('resampledData');
Meteor.subscribe('resampledData');

当然,正如杰弗里所提到的,如果重新计算方法很昂贵且经常执行,将重新计算的数据存储在单独的集合中会更有效。

答案 1 :(得分:2)

我认为这确实是你正在处理的与mongo相关的问题。 Meteor并不关心光标的外观或者生成所请求文档集的复杂程度。

Mongo采样解决方案通常需要generating a new field which will be used explicitly for sample。在你的情况下,虽然timestamp看起来很好用。

所以我认为您需要做的就是在服务器上保留一组示例数据或示例时间戳。

生成样本:

var nextTimestamp = 0;
var sampleArray = [];
data.find({},{sort: {timestamp: 1}} ).forEach( doc ){
  if ( ! nextTimestamp || doc.timestamp > nextTimeStamp ){
    if ( ! nextTimestamp )
      nextTimestamp = doc.timestamp;
    else {
      while ( nextTimestamp < doc.timestamp ){
        nextTimestamp += 1000 * 60 * 10; //assumed timestamps are in milliseconds but step size can be whatever you need
      }
    }
    sampleArray.push( doc );
  }
}}; 

您可能希望在时间戳上有一个索引来快速排序。我通常会在创建集合后在下一行中运行它。

data._ensureIndex( {timestamp: 1} );

这是否是一个好的解决方案取决于您创建后可以重复使用sampleArray的程度。因此,如果您的时间戳集合在客户端之间共享,请保存示例服务器端并将其用于多个客户端。如果同一客户端重用相同的样本数据,则保存并重用。如果您需要使用新数据进行更新,请使用$ gt查询仅处理需要添加到样本中的数据点。

例如,您可以在返回sampleArray的发布函数中使用上述内容,并使用observeChanges保持样本最新。

var handle data.find({timestamp: {$gt: nextTimestamp}}).observeChanges({
  added: function( id, doc ){
    //selector is not getting updated in the observeChanges so I think you need to keep checking timestamp
    if ( doc.timestamp > nextTimestamp ){
      while ( nextTimestamp < doc.timestamp ){
        nextTimestamp += 1000 * 60 * 10;
      }
      self.added( 'clientCollection', id, doc ) // self needs to be the thisObject of a publish 
    }
  });
});
self.onStop( function(){
  handle.stop();  // self needs to be the thisObject of a publish
});