Database 流星一次;“静态”;发布而不跟踪集合

Database 流星一次;“静态”;发布而不跟踪集合,database,meteor,publish-subscribe,Database,Meteor,Publish Subscribe,假设一个Meteor应用程序需要向每个客户端发送相同的10000个文档集合 在较高的层次上,我知道服务器对每个客户端订阅都做一些簿记——即,它跟踪订阅的状态,以便能够为客户端发送适当的更改。但是,如果每个客户机都有相同的大型数据集,并且每个文档都有许多字段,那么这种效率会非常低 似乎在那里,最初的查询已经发布,并且再也没有更改过。这似乎是一种更有效的方法 在当前版本的Meteor(0.6.5.1)中是否有正确的方法来实现这一点 编辑:澄清一下,这个问题与客户端反应性无关。它是关于减少服务器端跟踪

假设一个Meteor应用程序需要向每个客户端发送相同的10000个文档集合

在较高的层次上,我知道服务器对每个客户端订阅都做一些簿记——即,它跟踪订阅的状态,以便能够为客户端发送适当的更改。但是,如果每个客户机都有相同的大型数据集,并且每个文档都有许多字段,那么这种效率会非常低

似乎在那里,最初的查询已经发布,并且再也没有更改过。这似乎是一种更有效的方法

在当前版本的Meteor(0.6.5.1)中是否有正确的方法来实现这一点

编辑:澄清一下,这个问题与客户端反应性无关。它是关于减少服务器端跟踪客户端集合的开销。

一个相关问题:

更新:事实证明,在Meteor 0.7或更早版本中这样做会导致一些严重的性能问题。看看我们是如何解决这个问题的。

Statics.find({},{reactive:false})

编辑以反映评论:

您是否有一些信息表明reactive:false参数只是客户端?你可能是对的,这是一个合理的,也许是可能的解释。我没有时间检查,但我认为这可能也是一个服务器端指令,表示不要轮询mongo结果集。愿意学习

你说

However, this is horribly inefficient if each client has the same large data set where each document has many fields.
现在我们可能正在讨论服务器代码的效率,以及它对mongo源代码的轮询,以查找在服务器之外发生的更新。请再提一个问题,这远远超出我的回答能力!我怀疑这种情况会在每个连接的客户端发生一次,更有可能是应用服务器信息和mongo服务器之间的同步


您发出的客户机请求(包括排序)应全部标记为非反应性。这与您是否可以向它们发出排序指令,或者是否可以通过其他反应性重新触发它们是不同的,但不需要包括到服务器的跳闸。一旦每个文档到达客户端,它就会被缓存。你仍然可以做任何minimongo做的事情,不会损失能力。没有客户端询问服务器是否有更新,您不需要关闭它。服务器只在需要时推送数据。

此外,您可以将数据作为数组或对象脚本输出到js文件,将其最小化,然后作为独特的资源链接到该文件。看见 用于添加过期或缓存控制标头。你可能不想让meteor帮你打包


这将是最小的流量,并且可以使站点的后续加载更快。

我认为使用手动发布(
This.added
)仍然可以消除服务器观察数据更改所产生的开销。观察者需要手动添加,或者通过返回Collection.curser创建

如果数据集很大,您可能还担心为每个客户机保存数据副本的开销。要消除这种情况,可以在本地复制集合并停止订阅

var staticData = new Meteor.Collection( "staticData" );

if (Meteor.isServer ){
  var dataToPublish = staticData.find().fetch();  // query mongo when server starts

  Meteor.publish( "publishOnce" , function () {
    var self = this;
    dataToPublish.forEach(function (doc) {
      self.added("staticData", doc._id, doc);  //sends data to client and will not continue to observe collection
    });
  });
}

if ( Meteor.isClient ){
  var subHandle = Meteor.subscribe( "publishOnce" );  // fills client 'staticData' collection but also leave merge box copy of data on server

  var staticDataLocal = new Meteor.Collection( null );  // to store data after subscription stops

  Deps.autorun( function(){
    if ( subHandle.ready() ){
      staticData.find( {} ).forEach( function ( doc ){ 
        staticDataLocal.insert( doc );  // move all data to local copy
      });
      subHandle.stop();  // removes 'publishOnce' data from merge box on server but leaves 'staticData' collection empty on client
    }
  });
}
更新:我在代码中添加了注释,以使我的方法更加清晰。订阅句柄上的meteor docs for
stop()
“这通常会导致服务器指示客户端从客户端缓存中删除订阅数据”,因此可能有一种方法可以停止将数据保留在客户端上的订阅(从合并框中删除)。这将非常理想,并避免客户端上的复制开销


无论如何,使用
set
flush
的原始方法也会将数据保留在合并框中,所以这可能是正确的

作为对Meteor调用的响应,返回一组文档(使用fetch())而不进行响应或记录。在客户端上,当您执行查询或从会话中检索密钥时,创建一个dep,并且它在客户端上是被动的

Mini mongo只是通过语法解释您和数据之间的dsl来执行js数组/对象操作。

这一新功能使一次性发布到客户端集合成为可能

var staticData = new Meteor.Collection ('staticData');

if ( Meteor.isServer ){

  FastRender.onAllRoutes( function(){
    this.find( staticData, {} );
  });
}

正如您在Google Groups中指出的,您应该使用Meteor方法向客户端发送静态数据。

还有一种方法可以避免异步问题。

这是一种客户端功能。我说的是服务器端的订阅跟踪。例如,如果集合按
会话
变量排序,那么客户端可能仍然需要反应式游标。顺便说一句,我认为您在问题中添加了条件,然后有人对我的两个正确答案投了否决票。面对其他人,他们认为这些答案很有帮助。可能不是出于这种(自由)合作的精神。我对你的答案投了反对票,因为我认为你误解了这个问题,你的答案具有误导性。有关
find
的反应性的详细信息,请参阅。您不希望客户端对静态订阅的反应性,这一点都不是真的。同样,一个具体的例子是,如果您在客户端更改排序顺序。如果您的游标是非反应的,那么如果您更新了排序参数,它们不会改变。问题不是服务器在不需要数据时不会推送数据;这是因为服务器不必要地跟踪客户端数据。如果您使用不同的排序顺序(无论是否为被动排序)重新提交助手,您的模板将发生更改。很抱歉,这是一场激烈的比赛。1) 反应!=以不同的顺序检索。2) 我们同意查找的参考号。你只看到clients这个词(实际上并不存在),因为你用自己的方式来解释这个词。我将其理解为“监视更改并重新发布”。如果mongo db从另一个应用程序获得插入,则在这种情况下,非反应性可能意味着不继续重新填充db服务器。我们不需要说服对方