【问题标题】:Bug with multiple cursors in a publication? [duplicate]出版物中有多个光标的错误? [复制]
【发布时间】:2016-06-04 10:44:35
【问题描述】:

我正在编写通知系统(如 facebook 通知)。所以我有一个通知集合,其中的每个文档都有一个“actorId”字段,该字段存储调用该通知的用户的_id。我想在一个出版物中发布这些通知的最新通知和演员信息。所以这是我的发布功能:

Meteor.publish("myNotifications", function () {
    let notificationCursor = Notifications.find({receiver: this.userId});

    // get an array of actorIds, so we can fetch users' info in a single query
    let actorIds = [];
    notificationCursor.forEach(function(notification) {
        actorIds.push(notification.actor);
    });

    return [
        notificationCursor,
        Meteor.users.find({_id: { $in: actorIds }})
    ];
});

我使用 React。这是我的组件:

NotificationBlock = React.createClass({
    mixins: [ReactMeteorData],
    getMeteorData() {
        let data = {
            notifications: []
        };
        let handle = Meteor.subscribe('myNotifications');
        if (handle.ready()) {
            data.notifications = Notifications.find({}).fetch();
        }
        return data;
    },
    renderNotifications() {
        let list = [];
        _.each(this.data.notifications, notification => {
            let actor = Meteor.users.findOne(notification.actorId);
            list.push(
                <li key={notification._id}>
                    {actor.profile.name} did something...
                </li>
            );
        });
        return list;
    },
    render() {
        return (
            <ul>
                {this.renderNotifications()}
            </ul>
        );
    }
});

问题是,当有新通知时,似乎只有通知通过“myNotifications”发布发布。该新通知的演员信息未通过。所以客户端控制台显示一个错误,指出在反应组件的这一行中未定义“演员”:

{actor.profile.name} did something...

但如果我刷新浏览器,新通知会正确显示(带有演员的信息),控制台中完全没有任何错误!

我的猜测是,当在单个出版物中发布多个游标时,只有那些具有“添加”、“更改”、“删除”事件的集合的游标会被更新,对吧?这就是为什么 "Meteor.users.find({_id: { $in: actorIds }})" 不包含新用户信息的原因,尽管它的参数已更改。

【问题讨论】:

  • 另请参阅common mistakes 了解此处的其他一些问题,例如发布未过滤的用户。

标签: meteor


【解决方案1】:

这种集合连接问题的经典解决方案是使用reywood:publish-composite 包。这样您的出版物将变为:

Meteor.publishComposite('myNotifications', {
  find: function() {
    return Notifications.find({receiver: this.userId});
  },
  children: [
    {
      find: function(notification) {
        return Meteor.users.find(
          { _id: notification.actor },
          { fields: { profile: 1 } });
      }
    }
  ]
});

还要注意从 users 集合返回的字段的限制。您真的不想为每个 other 用户返回整个用户对象。

【讨论】:

  • 感谢您指向该包,尽管它没有像 b/c 那样优化,但您必须运行单独的查询来获取每个通知的用户信息。我确实发现这个问题已经众所周知,并且写在 discovermeteor.com/blog/reactive-joins-in-meteor 中。顺便说一句,我确实限制了从用户集合返回的字段,但从问题中的代码中删除以简化它。
猜你喜欢
  • 2012-07-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多