如何根据另一个的内容对集合进行反应?

时间:2013-07-27 21:08:22

标签: meteor

简而言之,我想这样做:

Meteor.publish('items', function(){ 
  return Item.find({categoryId: Categories.find({active: true} });
});

作为“类别”一部分的“有效”标志会定期更改。

我还尝试通过利用Categories集合上的反应来unsub / resub到Items集合,并且它可以工作,不幸的是它会重新触发对Categories集合的任何修改,无论它是否影响'active'标志。

我有什么选择?

4 个答案:

答案 0 :(得分:1)

当类别在服务器上标记为非活动状态时,没有解决本地未被“删除”的问题。解决方案(ish)是:

客户:

 Categories.find({active: true}).observeChanges({
    added: function(){
      itemsHandle && itemsHandle.stop();
      itemsHandle = Meteor.subscribe("items");      
    }
  });

服务器:

Meteor.publish('items', function(){
  var category = Categories.findOne({active: true});
  return category && Items.find({categoryId: Categories.findOne({active: true}._id);
});

我意识到这并不完美(仍然使用客户端代码),但它的工作原理和我能想到的最干净。我希望它可以帮助别人!

答案 1 :(得分:0)

可能的解决方案是创建依赖项对象,监视所有类别更改,并在切换活动标志时触发dep更改。这些方面的东西:

var activeCount = Categories.find({active: true}).count();

var activeDep = new Deps.Dependency();


Deps.autorun(function() {
    var activeCountNow = Categories.find({active: true}).count();
    if(activeCountNow !== activeCount) {
        activeCount = activeCountNow;
        activeDep.changed();
    }
});

Meteor.publish('items', function(){ 
    activeDep.depend();
    return Item.find({categoryId: Categories.find({active: true} });
});

注意:我只是验证活动类别的数量是否有变化,这样我就不必将活动列表保留在内存中。根据您的应用的工作方式,这可能适用也可能不适用。


编辑:评论中提到的双面风味:

<强>客户端:

var activeCount = Categories.find({active: true}).count();
var activeDep = new Deps.Dependency();

Deps.autorun(function() {
    var activeCountNow = Categories.find({active: true}).count();
    if(activeCountNow !== activeCount) {
        activeCount = activeCountNow;
        activeDep.changed();
    }
});

Deps.autorun(function(){
    activeDep.depend();
    Meteor.subscribe('items', new Date().getTime());
});

服务器

Meteor.publish('items', function(timestamp) {
    var t = timestamp;
    return Item.find({categoryId: Categories.find({active: true} });
});

答案 2 :(得分:0)

Meteor.startup(function() {
    Categories.find().observe({
        addedAt: function(doc) {
            trigger();
        },
        changedAt: function(doc, oldDoc) {
            if(doc.active != oldDoc.active) {
                trigger();
            }
        },
        removedAt: function(oldDoc) {
            trigger();
        }
    });
});

现在,trigger函数应该导致重新运行发布。这一次,当它在客户端(更改订阅参数)时很容易。我不确定如何在服务器上执行此操作 - 也许再次运行publish

答案 3 :(得分:0)

我使用以下发布来解决类似的问题。我认为只有查询的一行嵌套限制了反应性。在发布函数中打破一个查询似乎可以避免这个问题。

//on server
Meteor.publish( "articles", function(){
  var self= this;
  var subscriptions = [];

  var observer = Feeds.find({ subscribers: self.userId }, {_id: 1}).observeChanges({
    added: function (id){
             subscriptions.push(id);                                       
    },

    removed: function (id){
                subscriptions.splice( subscriptions.indexOf(id)) , 1);
    }

  });

  self.onStop( function() {
                observer.stop();
  });

  var visibleFields = {_id: 1, title: 1, source: 1, date: 1, summary: 1, link: 1};

  return Articles.find({ feed_id: {$in: subscriptions} }, { sort: {date: -1}, limit: articlePubLimit, fields: visibleFields } );

});

//on client anywhere
Meteor.subscribe( "articles" );

如果您认为可以接受,则另一个SO example从客户端通过订阅获取搜索条件。


更新:由于OP努力实现这一目标,我提出了gist并在meteor.com上启动了一个工作版本。如果您只需要发布功能,则如上所述。