clery00
clery00

Reputation: 251

Meteor Pub / Sub behaviour

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.

  1. The first subscription subscribes to the latest 50 posts, and sends the data to the MiniMongo collection Posts.

  2. 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

Answers (2)

Soubhik Mondal
Soubhik Mondal

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:

  1. You have to subscribe in order to receive the data from the server-side database.

  2. 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

Abdelhamid Belarbi
Abdelhamid Belarbi

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

Related Questions