Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor publish/subscribe strategies for unique client-side collections

Tags:

Using Meteor, I'm wondering how best to handle different client-side collections that share the same server-side database collection. Consider the following example: I have a User collection, and on my client-side I have a list of users that are friends and I have a search feature that performs a query on the entire users database, returning a list of usernames that match the query.

On the Publish server-side method, I have two queries against the same collection that return different sets of documents. Should this data go into two separate collections on the client-side? Or should all of the User documents that match both queries end up in the same collection? If the latter, would I then duplicate code used for both the server-side and client-side query?

On the server:

Meteor.publish('searchResults', function(query){   var re = new RegExp(query, 'i')   return Users.find({ 'name' : {$regex: re}}) }) 

On the client:

Session.set('searchQuery', null)  Meteor.autosubscribe(function(){   Meteor.subscribe('searchResults', Session.get('searchQuery')) })  Template.search.events = {   'keyup #user-search' : function(e){     Session.set('searchQuery', e.target.value)   } }  _.extend(Template.search, {    searchResults: function() {     var re = new RegExp(Session.get('searchQuery'), 'i')     return Users.find({ 'name' : {$regex: re}})   } }) 

This seems like a plausible solution, but not an optimal one. What if I wanted to create a new client-side collection that consisted of search results from multiple server-side Collections?

like image 531
bento Avatar asked Sep 01 '12 00:09

bento


1 Answers

In a shared area:

function getSearchUsers(query) {   var re = new RegExp(query, "i");   return Users.find({name: {$regex: re}}); }  function getFriendUsers() {   return Users.find({friend: true});    // or however you want this to work } 

On the server:

Meteor.publish("searchUsers", getSearchUsers); Meteor.publish("friendUsers", getFriendUsers); 

On the client:

Template.search.onCreated(function () {    var self = this;    self.autorun(function () {      self.subscribe("searchUsers", Session.get("searchQuery"));    }); });  Template.friends.onCreated(function () {   this.subscribe("friendUsers"); });  Template.search.helpers({   searchResults: function () {     return getSearchUsers(Session.get("searchQuery"));   } });  Template.friends.helpers({   results: function () {     return getFriendUsers();   } }); 

The key takeaway from this is that what happens behind the scenes when the data is getting transferred over the wire isn't obvious. Meteor appears to combine the records that were matched in the various queries on the server and send this down to the client. It's then up the client to run the same query again to split them apart.

For example, say you have 20 records in a server-side collection. You then have two publishes: the first matches 5 records, the second matches 6, of which 2 are the same. Meteor will send down 9 records. On the client, you then run the exact same queries you performed on the server and you should end up with 5 and 6 records respectively.

like image 112
matb33 Avatar answered Oct 13 '22 14:10

matb33