发布/订阅同一服务器集合的多个子集

mat*_*b33 36 collections publish-subscribe meteor

编辑:这个问题,一些答案,以及一些评论,包含了很多错误的信息.见流星收集,发布和预订是如何工作的出版的准确理解和订阅到同一台服务器收集的多个子集.


如何在服务器上发布单个集合的不同子集(或"视图")作为客户端上的多个集合?

这里有一些伪代码来帮助说明我的问题:

items 在服务器上的集合

假设我items在服务器上有一个包含数百万条记录的集合.我们还假设:

  1. 50个记录的enabled属性设置为true,和;
  2. 100条记录的processed属性设置为true.

所有其他人都设置为false.

items:
{
    "_id": "uniqueid1",
    "title": "item #1",
    "enabled": false,
    "processed": false
},
{
    "_id": "uniqueid2",
    "title": "item #2",
    "enabled": false,
    "processed": true
},
...
{
    "_id": "uniqueid458734958",
    "title": "item #458734958",
    "enabled": true,
    "processed": true
}
Run Code Online (Sandbox Code Playgroud)

服务器代码

让我们发布同一服务器集合的两个"视图".一个将发送一个包含50个记录的游标,另一个将向下发送一个包含100个记录的游标.在这个虚构的服务器端数据库中有超过4.58亿条记录,客户端不需要知道所有这些(事实上,在这个例子中将它们全部发送下去可能需要几个小时):

var Items = new Meteor.Collection("items");

Meteor.publish("enabled_items", function () {
    // Only 50 "Items" have enabled set to true
    return Items.find({enabled: true});
});

Meteor.publish("processed_items", function () {
    // Only 100 "Items" have processed set to true
    return Items.find({processed: true});
});
Run Code Online (Sandbox Code Playgroud)

客户代码

为了支持延迟补偿技术,我们不得不Items在客户端上声明一个集合.应该明白缺陷的位置:如何区分Itemsfor enabled_itemsItemsfor processed_items

var Items = new Meteor.Collection("items");

Meteor.subscribe("enabled_items", function () {
    // This will output 50, fine
    console.log(Items.find().count());
});

Meteor.subscribe("processed_items", function () {
    // This will also output 50, since we have no choice but to use
    // the same "Items" collection.
    console.log(Items.find().count());
});
Run Code Online (Sandbox Code Playgroud)

我当前的解决方案涉及猴子修补_publishCursor,以允许使用订阅名称而不是集合名称.但这不会做任何延迟补偿.每次写入都必须往返于服务器:

// On the client:
var EnabledItems = new Meteor.Collection("enabled_items");
var ProcessedItems = new Meteor.Collection("processed_items");
Run Code Online (Sandbox Code Playgroud)

随着猴子补丁到位,这将有效.但是进入离线模式并且客户端不会立即显示更改 - 我们需要连接到服务器以查看更改.

什么是正确的方法?


编辑:我刚刚重新审视了这个帖子,我意识到,就目前而言,我的问题和答案以及过多的评论带来了很多错误的信息.

它归结为我误解了发布 - 订阅关系.我认为,当您发布游标时,它将作为与来自同一服务器集合的其他已发布游标的单独集合登陆客户端.这根本不是它的工作原理.这个想法是客户端和服务器都有相同的集合,但它们集合中的不同之处.pub-sub合同协商哪些文档最终在客户端上.汤姆的回答在技术上是正确的,但缺少一些细节来扭转我的假设.我根据Tom的解释在另一个SO线程中回答了类似的问题,但请记住我对Meteor的pub-sub的原始误解:针对独特客户端集合的Meteor发布/订阅策略

希望这可以帮助那些遇到这个线程并且比任何事情都更加困惑的人!

Tom*_*man 34

当你想看项目时,你能不能只使用相同的查询客户端?

在lib目录中:

enabledItems = function() {
  return Items.find({enabled: true});
}
processedItems = function() {
  return Items.find({processed: true});
}
Run Code Online (Sandbox Code Playgroud)

在服务器上:

Meteor.publish('enabled_items', function() {
  return enabledItems();
});
Meteor.publish('processed_items', function() {
  return processedItems();
});
Run Code Online (Sandbox Code Playgroud)

在客户端

Meteor.subscribe('enabled_items');
Meteor.subscribe('processed_items');

Template.enabledItems.items = function() {
  return enabledItems();
};
Template.processedItems.items = function() {
  return processedItems();
};
Run Code Online (Sandbox Code Playgroud)

如果你考虑一下,这样做会更好,就好像你插入(本地)一个既启用又处理过的项目,它可以出现在两个列表中(如果你有两个独立的集合则相反).

注意

我意识到我有点不清楚,所以我已经扩展了一点,希望它有所帮助.


Llo*_*oyd 6

你可以制作两个这样的独立出版物.

服务器出版物

Meteor.publish("enabled_items", function(){
    var self = this;

    var handle = Items.find({enabled: true}).observe({
        added: function(item){
            self.set("enabled_items", item._id, item);
            self.flush();
        },
        changed: function(item){
            self.set("enabled_items", item._id, item);
            self.flush();
        }
    });

    this.onStop(function() {
        handle.stop();
    });
});

Meteor.publish("disabled_items", function(){
    var self = this;

    var handle = Items.find({enabled: false}).observe({
        added: function(item){
            self.set("disabled_items", item._id, item);
            self.flush();
        },
        changed: function(item){
            self.set("disabled_items", item._id, item);
            self.flush();
        }
    });

    this.onStop(function() {
        handle.stop();
    });
});
Run Code Online (Sandbox Code Playgroud)

客户订阅

var EnabledItems = new Meteor.Collection("enabled_items"),
    DisabledItems = new Meteor.Collection("disabled_items");

Meteor.subscribe("enabled_items");
Meteor.subscribe("disabled_items");
Run Code Online (Sandbox Code Playgroud)