Publishing/subscribing multiple subsets of the same server collection
- by matb33
How does one go about publishing different subsets (or "views") of a single collection on the server as multiple collections on the client?
Here is some pseudo-code to help illustrate my question:
items collection on the server
Assume that I have an items collection on the server with millions of records. Let's also assume that:
50 records have the enabled property set to true, and;
100 records have the processed property set to true.
All others are set to false.
items:
{
"_id": "uniqueid1",
"title": "item #1",
"enabled": false,
"processed": false
},
{
"_id": "uniqueid2",
"title": "item #2",
"enabled": false,
"processed": true
},
...
{
"_id": "uniqueid458734958",
"title": "item #458734958",
"enabled": true,
"processed": true
}
Server code
Let's publish two "views" of the same server collection. One will send down a cursor with 50 records, and the other will send down a cursor with 100 records. There are over 458 million records in this fictitious server-side database, and the client does not need to know about all of those (in fact, sending them all down would probably take several hours in this example):
var Items = new Meteor.Collection("items");
Meteor.publish("enabled_items", function () {
// Only 50 "Items" have enabled set to true
return Items.find({enabled: true});
});
Meteor.publish("processed_items", function () {
// Only 100 "Items" have processed set to true
return Items.find({processed: true});
});
Client code
In order to support the latency compensation technique, we are forced to declare a single collection Items on the client. It should become apparent where the flaw is: how does one differentiate between Items for enabled_items and Items for processed_items?
var Items = new Meteor.Collection("items");
Meteor.subscribe("enabled_items", function () {
// This will output 50, fine
console.log(Items.find().count());
});
Meteor.subscribe("processed_items", function () {
// This will also output 50, since we have no choice but to use
// the same "Items" collection.
console.log(Items.find().count());
});
My current solution involves monkey-patching _publishCursor to allow the subscription name to be used instead of the collection name. But that won't do any latency compensation. Every write has to round-trip to the server:
// On the client:
var EnabledItems = new Meteor.Collection("enabled_items");
var ProcessedItems = new Meteor.Collection("processed_items");
With the monkey-patch in place, this will work. But go into Offline mode and changes won't appear on the client right away -- we'll need to be connected to the server to see changes.
What's the correct approach?