发布/订阅Meteor返回整个Collection

时间:2016-01-19 16:08:50

标签: javascript mongodb meteor reactjs

我正在为我的Meteor应用程序实现发布/订阅架构。我还没有删除autopublish。我使用React和kadira:flow-routerkadira:react-layout。它工作正常。

这是我的发布代码(/lib/publications.js,虽然我也尝试使用/server/publications.js,但没有更改):

if (Meteor.isServer) {
    Meteor.publish("games", function() {
        return Games.find({});
    });

    Meteor.publish("game", function(gameId) {
        return Games.find({_id: gameId});
    });

    Meteor.publish("messages", function(gameId) {
        return Messages.find({gameId: gameId}, {sort: {createdAt: -1}});
    });
}

当然,如果我在/server中使用它,我不会添加if语句。我在路由器中订阅这些出版物(/lib/routing.js):

user.route('/game/:id', {
    name: 'game',
    subscriptions: function(params, queryParams) {
        this.register('messages', Meteor.subscribe('messages', params.id));
    },
// ...
});

然后我在React组件中获取数据(/client/components/pages/game_page.jsx):

// ...
mixins: [ReactMeteorData],
getMeteorData: function() {
    return {
        messages: Messages.find({}).fetch()
    }
},
// ...

我没有获得gameId等于传递参数的所有消息,而是获得所有游戏中的所有消息。如果我删除发布/订阅并只是要求这样的数据:

// ...
mixins: [ReactMeteorData],
getMeteorData: function() {
    return {
        messages: Messages.find({gameId: gameId}, {sort: {createdAt: -1}}).fetch()
    }
},
// ...

它完美无缺。知道为什么吗?我想我错过了一些东西:关于发布/订阅本身或关于在路由器中使用订阅。

2 个答案:

答案 0 :(得分:2)

您必须删除autopublish包,因为默认情况下它会发布集合中的所有内容。

根据我的理解,每个订阅都会在集合中公开一些文档,因此如果您有两个订阅同一个集合,那么当您查询集合时,您将可以访问两个订阅公开的所有文档,因此它是累积的。

答案 1 :(得分:1)

自动发布包将所有数据发布到客户端(就像您订阅了对所有集合执行Collection.find({})的发布一样)。这意味着,您的自定义发布/订阅在您的示例中实际上什么都不做,如果您查询这样的数据:

getMeteorData: function() {
    return {
        messages: Messages.find({}).fetch()
    }
},

您将获得所有消息,这是正确的行为。

无论如何,您应该始终在数据查询中进行显式查询,如下所示:

getMeteorData: function() {
    return {
        messages: Messages.find({gameId: gameId}, {sort: {createdAt: -1}}).fetch()
    }
},

因为如果您碰巧同时有两个不同的消息订阅(出于不同的目的,即一个订阅一个消息包含所有详细信息,另一个订阅包含不同详细信息/字段的不同消息),此数据查询{{1}会让你订阅两个订阅中订阅的文件的联合,它可能不会是你期望的。

因此,在您的情况下,请删除autopublish包,并在数据访问(Messages.find({}))中添加此显式查询。