Meteor 发布/订阅独特客户端集合的策略

Posted

技术标签:

【中文标题】Meteor 发布/订阅独特客户端集合的策略【英文标题】:Meteor publish/subscribe strategies for unique client-side collections 【发布时间】:2012-08-26 18:35:24 【问题描述】:

使用 Meteor,我想知道如何最好地处理共享相同服务器端数据库集合的不同客户端集合。考虑以下示例:我有一个 User 集合,在我的客户端我有一个 好友用户列表,我有一个搜索功能,可以对整个用户数据库执行查询,返回一个与查询匹配的用户名列表

在发布服务器端方法中,我有两个针对同一集合的查询,它们返回不同的文档集。这些数据是否应该在客户端进入两个单独的集合?还是应该将所有匹配两个查询的用户文档都放在同一个集合中?如果是后者,我会复制用于服务器端和客户端查询的代码吗?

在服务器上:

Meteor.publish('searchResults', function(query)
  var re = new RegExp(query, 'i')
  return Users.find( 'name' : $regex: re)
)

在客户端:

Session.set('searchQuery', null)

Meteor.autosubscribe(function()
  Meteor.subscribe('searchResults', Session.get('searchQuery'))
)

Template.search.events = 
  'keyup #user-search' : function(e)
    Session.set('searchQuery', e.target.value)
  


_.extend(Template.search, 

  searchResults: function() 
    var re = new RegExp(Session.get('searchQuery'), 'i')
    return Users.find( 'name' : $regex: re)
  
)

这似乎是一个合理的解决方案,但不是最佳解决方案。如果我想创建一个新的客户端集合,其中包含来自多个服务器端集合的搜索结果,该怎么办?

【问题讨论】:

【参考方案1】:

在共享区域中:

function getSearchUsers(query) 
  var re = new RegExp(query, "i");
  return Users.find(name: $regex: re);


function getFriendUsers() 
  return Users.find(friend: true);    // or however you want this to work

在服务器上:

Meteor.publish("searchUsers", getSearchUsers);
Meteor.publish("friendUsers", getFriendUsers);

在客户端:

Template.search.onCreated(function () 
   var self = this;
   self.autorun(function () 
     self.subscribe("searchUsers", Session.get("searchQuery"));
   );
);

Template.friends.onCreated(function () 
  this.subscribe("friendUsers");
);

Template.search.helpers(
  searchResults: function () 
    return getSearchUsers(Session.get("searchQuery"));
  
);

Template.friends.helpers(
  results: function () 
    return getFriendUsers();
  
);

从中得出的关键结论是,当数据 通过电线传输并不明显。流星似乎结合 在服务器上的各种查询中匹配的记录并将其发送 下到客户。然后客户端再次运行相同的查询以进行拆分 他们分开。

例如,假设您在服务器端集合中有 20 条记录。然后你有 两次发布:第一次匹配 5 条记录,第二次匹配 6 条记录,其中 2 条是 相同。 Meteor 将发送 9 条记录。然后在客户端上运行确切的 您在服务器上执行的相同查询,您最终应该得到 5 和 6 分别记录。

【讨论】:

只是想说明一下,我关于 Meteor 如何“组合”记录的信息可能不准确或不真实。如果 Meteor 开发人员或更了解的人可以确认,请确认。我的假设是基于我个人的观察。 看来我对合并的观察是正确的。请参阅此答案中的“合并框”部分:***.com/a/13867122/962223 当我将搜索功能放在共享文件夹中时,例如lib 发布函数可以找到它们。当我将它们与发布函数放在同一个文件中时,它们会被发布函数找到,但在客户端上不可见。想法? 将它们放入 Meteor.startup() 函数中! 噢噢噢噢。这更有意义。您的意思是,无论您有多少发布/订阅功能,用户集合都将包含来自每个订阅的所有记录,您必须查询这些记录以提取您想要的记录。【参考方案2】:

我参加聚会有点晚了,但是有一种方法可以在客户端上为一个服务器集合的子集提供单独的集合。 在此示例中,我有一个名为 entities 的服务器集合,其中包含有关 polygonsrectangles 的信息。 共享代码(lib 文件夹):

// main collection (in this example only needed on the server
Entities = new Meteor.Collection('entities');
// partial collections
RectEntities = new Mongo.Collection('rectEntities');
PolyEntities = new Mongo.Collection('polyEntities');

客户端代码:

// this will fill your collections with entries from the Entities collection
Meteor.subscribe('rectEntities');
Meteor.subscribe('polyEntities');

请记住,订阅的名称需要与发布的名称匹配(但不是集合本身的名称) 服务器代码:

Meteor.publish('rectEntities', function()
    Mongo.Collection._publishCursor( Entities.find(shapeType: 'rectangle'), this, 'rectEntities'); 
    this.ready();
);

Meteor.publish('polyEntities', function()
    Mongo.Collection._publishCursor( Entities.find(shapeType: 'polygon'), this, 'polyEntities'); 
    this.ready();
);

感谢 user728291 使用_publishCursor() 提供更简单的解决方案!_publishCursor() 函数的第三个参数是新集合的名称。 来源:http://docs.meteor.com/#/full/publish_added

【讨论】:

使用未记录的_publishCursor,您的代码可以短很多。例如Meteor.publish('polyEntities', function() Mongo.Collection._publishCursor( Entities.find(shapeType: 'polygon'), this, 'polyEntities'); this.ready();); @user728291 您将如何处理 PolyEntities 集合的更新? 您必须编写自定义Meteor.methods。客户端存根将更新/插入到PolyEntities(可能还有RectEntities),服务器将更新/插入到Entities 我发现了另一种简单的方法:只需通过 PolyEntities._collection_.update() 更新集合的本地副本,然后让这个 observeChanges() 方法监视这些更改并将它们发布到 Entities 集合。可悲的是,它的性能似乎并不好.. 我对本地集合所做的更改稍后会在订阅更新到来时被覆盖.. 虽然 m 流星方法应该更快 是的,meteor 方法没有性能问题,唯一的缺点是,您必须一直手动调用该方法,并且一旦更新集合就无法触发它..【参考方案3】:

使用publish-composite 包

// main collection
Entities = new Meteor.Collection('entities');

// partial collections only client side
RectEntities = new Mongo.Collection('rectEntities');
PolyEntities = new Mongo.Collection('polyEntities');

// server publish
Meteor.publishComposite("rectEntities", function(someParameter) 
    return 
            collectionName:'rectEntities',
            find: function() 
                return Entities.find(shapeType: 'rectangle');
            ,
            children: []
    
);
Meteor.publishComposite("polyEntities", 
        collectionName:'polyEntities',
        find: function() 
            return Entities.find(shapeType: 'polygon');
        ,
        children: []
);

来源:http://braindump.io/meteor/2014/09/20/publishing-to-an-alternative-clientside-collection-in-meteor.html

【讨论】:

如何在客户端“消费”这个?

以上是关于Meteor 发布/订阅独特客户端集合的策略的主要内容,如果未能解决你的问题,请参考以下文章

MeteorJS - 如何防止匿名客户端订阅集合?

流星集合不更新客户端上的订阅

在 Meteor 中,如何只查询给定订阅的记录?

客户端订阅未从 Meteor 服务器发布接收数据

Meteor:发布/订阅问题

在新数据到达 Meteor 时对其进行动画处理