Meteor的发布/订阅功能

时间:2016-11-29 22:22:03

标签: mongodb meteor collections publish-subscribe

我在使用Meteor的发布/订阅功能时遇到了不一致的结果,我怀疑它是很多开发人员在Meteor内置的MVP阈值成为生产时的混乱之源应用

也许这是MergeBox的限制:

让我们说我有一个名为Events的集合,其中我有面向文档的结构,即嵌套数组,对象。 Events文档可能如下所示:

// an Events document //
{
  _id: 'abc',
  name: 'Some Event',
  participation: {
    'userOneId': {
        games: {
          'gameOneId': {
            score: 100,
            bonus: 10
          }
        },
        {
          'gameTwoId': : {
            score: 100,
            bonus: 10
          }
        }
      }
    },
    'userTwoId': {
        games: {
          'gameOneId': {
            score: 70,
            bonus: 15
          }
        },
        contests: {
          'contestOneId': [2, 3, 6, 7, 4],
          'contestTwoId': [9, 3, 7, 2, 1],
        }
      }
    },
  }
}

因此,在这些活动中,用户可以选择参加某些类型的游戏和某些类型的比赛。

现在,我想根据用户限制对Events集合的订阅(仅显示此用户participation),有时我只对一个子集的更改感兴趣数据(例如,仅显示用户在游戏上的分数')。

所以我创建了这样的出版物:

Meteor.publish("events.participant", function(eventId, userId) {
  if(!Meteor.users.findOne({_id: this.userId})) return this.ready();
  check(eventId, String);
  check(userId, String);
  const includeFields = {
    name: 1,
    [`participation.${userId}`]: 1
  };
  return Events.find({_id: eventId}, {fields: includeFields});
});

如果我这样做,该出版物似乎在客户端上正常工作:

// in onCreated of events template //
template.autorun(function() {
  const 
    eventId = FlowRouter.getParam('id'),
    userId = Meteor.userId(),
    subscription = template.subscribe('events.participant', eventId, userId);
  if (subscription.ready()) {
    const event = Events.findOne({_id: eventId}, parseIncludeFields(['name', `participation.${userId}`]));
    template.props.event.set(event);
  }
});

令人高兴的是,我可以使用返回的事件文档,该文档仅包含name字段和所有用户的participation数据。

但是,稍后,如果我这样做,则在另一个模板中:

// in onCreated of games template //
template.autorun(function() {
  const
    eventId = FlowRouter.getParam('id')
    gameId = FlowRouter.getParam('gameId'),
    userId = Meteor.userId(),
    subscription = template.subscribe('events.participant', eventId, userId);
  if(subscription.ready()) {
    const event = Events.findOne({_id: eventId}, {fields: {[`participation.${userId}.games.${gameId}`]: 1}});
    template.props.event.set(event);
  }
});

有时会在event.participation[userId].games[gameId]取回数据,有时我不会 - 假设gameId处的对象是非 - 存在,即使它存在于Mongo文档中,订阅也应该包含它。的为什么吗

唯一的区别是对Events.findOne()的两次调用之间的区别在于,在后者中,我没有请求name字段。但是,如果这是一个问题,为什么?。如果minimongo已经有文件,谁在乎我是否要求部分文件?

两个模板中的订阅都是相同的 - 我这样做是因为games模板在路线上可用,因此用户可以直接转到游戏网址,绕过{{1完全模板,所以我想确保客户端具有正确呈现所需的文档。

我解决这个问题的唯一方法是在游戏模板中对服务器进行直接的Meteor方法调用以获取感兴趣的子集,但这似乎是一个警察。

如果您已经读过这篇文章,那么您就是冠军!

0 个答案:

没有答案