Reputation: 1929
I am implementing a publish/subscribe architecture for my Meteor app. I have not removed autopublish
yet. I use React and kadira:flow-router
with kadira:react-layout
. It works fine.
This is my publish code (/lib/publications.js
though I tried with /server/publications.js
as well, no change):
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}});
});
}
Of course if I use it in /server
I don't add the if
statement. I subscribe to those publications in the router like this (/lib/routing.js
):
user.route('/game/:id', {
name: 'game',
subscriptions: function(params, queryParams) {
this.register('messages', Meteor.subscribe('messages', params.id));
},
// ...
});
And then I get data in the React component like so (/client/components/pages/game_page.jsx
):
// ...
mixins: [ReactMeteorData],
getMeteorData: function() {
return {
messages: Messages.find({}).fetch()
}
},
// ...
Instead of getting all messages that have gameId
equal to the passed argument I get ALL of the messages from ALL of the games. If I remove the publish/subscribe and just ask for data like this:
// ...
mixins: [ReactMeteorData],
getMeteorData: function() {
return {
messages: Messages.find({gameId: gameId}, {sort: {createdAt: -1}}).fetch()
}
},
// ...
It works perfectly fine. Any idea why? I think I am missing something: either about publish/subscribe itself or about using subscribe in router.
Upvotes: 1
Views: 368
Reputation: 317
Autopublish package publishes all data to client (it is like you subscribed to a publication that does Collection.find({})
on all collections). It means, that your custom publication/subscribtion actually does nothing in your example, and if you query data like this:
getMeteorData: function() {
return {
messages: Messages.find({}).fetch()
}
},
you will just get all messages, and that's correct behavior.
Anyway, you should always make the explicit query in data query like this:
getMeteorData: function() {
return {
messages: Messages.find({gameId: gameId}, {sort: {createdAt: -1}}).fetch()
}
},
because if you happen to have two different messages subscriptions at the same time (for different purposes, i.e. one subscription for one message with all details and another for different messages with less details/fields), this data query Messages.find({})
will get you union of the documents subscribed in both subscriptions, and it probably won't be what you would expect.
So, in your case, remove autopublish package, and add this explicit query in data access (messages: Messages.find({gameId: gameId}, {sort: {createdAt: -1}}).fetch()
).
Upvotes: 1
Reputation: 1143
You'll have to remove the autopublish package because by default it publishes everything in the collection.
From my understanding, every subscription exposes some documents in the collection so if you had you have two subscriptions for the same collection then when you query your collection you will have access to all the documents that two subscriptions expose so it is accumulative.
Upvotes: 2