Reputation: 251
I'm currently implementing a realtime search function in my app and I've come across some behaviour which I'm confused about.
The background is: I have two subscriptions from the same MongoDB database on my server, named posts
.
The first subscription subscribes to the latest 50 posts, and sends the data to the MiniMongo collection Posts
.
The second subscriptions subscribes to the post matching whatever search is entered by the user, and sends this data to MiniMongo collection PostsSearch
as per below.
// client
Posts = new Mongo.Collection('posts');
PostsSearch = new Mongo.Collection('postsSearch');
// server
Meteor.publish('postsPub', function(options, search) {
return Posts.find(search, options);
});
Meteor.publish('postsSearchPub', function(options, search) {
var self = this;
var subHandle = Posts.find(search, options).observeChanges({
added: function (id, fields) {
self.added("postsSearch", id, fields);
}
});
self.ready();
});
My question is, we know from the docs:
If you pass a name when you create the collection, then you are declaring a persistent collection — one that is stored on the server and seen by all users. Client code and server code can both access the same collection using the same API.
However this isn't the case with PostsSearch
. When a user starts searching on the client, the functionality works perfectly as expected - the correct cursors are sent to the client.
However I do not see a postsSearch
in my MongoDB database and likewise, PostsSearch
isn't populated on any other client other than my own.
How is this happening? What is self.added("postsSearch", id, fields);
appearing to do that's it's able to send cursors down the wire to the client but not to the MongoDB database.
Upvotes: 2
Views: 262
Reputation: 2666
According to this doc, self.added("postsSearch", id, fields);
informs the client-side that a document has been added to the postsSeach
collection.
And according to Meteor.publish:
Alternatively, a publish function can directly control its published record set by calling the functions added (to add a new document to the published record set), ...
So I'm guessing that self.added
does both of these operations: Adds a document to the published record set, and informs the client (that has subscribed to the current publication) of this addition.
Now if you see Meteor.subscribe:
When you subscribe to a record set, it tells the server to send records to the client. The client stores these records in local Minimongo collections, with the same name as the collection argument used in the publish handler's added, changed, and removed callbacks. Meteor will queue incoming records until you declare the Mongo.Collection on the client with the matching collection name.
This suggests 2 things:
You have to subscribe
in order to receive the data from the server-side database.
Some kind of client-side code must exist in order to create a client-only postsSearch
collection. (this is because you said, this collection doesn't exist on server-side database).
The 2nd point can be achieved quite easily, for example:
if(Meteor.isClient) {
postsSearch = new Mongo.Collection(null);
}
In the above example, the postsSearch
collection will exist only on the client and not on the server.
And regarding the 1st, being subscribed to postsSearchPub
will automatically send data for the postsSearch
collection to the client (even if said collection doesn't exist in the server-side database. This is because of the explicit call to self.added
).
Something to check out: According to this doc, self.ready();
calls the onReady
callback of the subscription. It would be useful to see what is there in this callback, perhaps the client-only postsSearch
collection is defined there?
Upvotes: 1
Reputation: 609
From the doc:
this.added(collection, id, fields)
Call inside the publish function.
Informs the subscriber that a document has been added to the record set.
This means that the line self.added("postsSearch", id, fields);
emulates the fact that an insert has been done to the PostsSearch
collection although it's obviously not the case.
Concerning the absence of MongoDB collection, it could be related to Meteor laziness which creates the MongoDB collection at first insert, not sure though.
Upvotes: 0