Meteor DevShop 10, 2013-Dec-05
When data changes in your database, everybody's web UI updates automatically without you having to write any custom code.
Meteor.publish("top-scores", function (gameId) {
check(gameId, String);
return Scores.find({game: gameId},
{sort: {score: -1}, limit: 5, fields: {score: 1, user: 1}});
});
observeChanges is a brand new API in Meteor's Mongo client interface.
handle = Messages.find({room: roomId}).observeChanges({
added: function (id, fields) {...},
changed: function (id, fields) {...},
removed: function (id) {...}
})
var results = {};
var pollAndDiff = function () {
cursor.rewind();
var oldResults = results;
results = {};
cursor.forEach(function (doc) {
results[doc._id] = doc;
if (_.has(oldResults, doc._id))
callbacks.changed(doc._id, changedFieldsBetween(oldResults[doc._id], doc));
else
callbacks.added(doc._id, doc);
});
_.each(oldResults, function (doc, id) {
if (!_.has(results, id))
callbacks.removed(id);
});
};
setInterval(pollAndDiff, 10 * 1000);
whenWeWriteToTheCollection(pollAndDiff);
We're going to let the database tell us what changed
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Run the query and cache:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "insert", id: "www", {game: "skee-ball", user: "glasser", score: 1000}}
Ignore it: does not match selector.
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "insert", id: "aaa", {game: "carrom", user: "glasser", score: 10}}
Ignore it: selector matches, but the score is not high enough.
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "remove", id: "ppp"}
Ignore it: removing something we aren't publishing can't affect us (unless skip option is set!)
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "update", id: "ccc", {$set: {color: "blue"}}}
This is a document not currently in the cursor. This change does not affect the selector or the sort criteria, so it can't affect the results. Ignore it!
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "update", id: "xxx", {$set: {color: "red"}}}
This is a document in the cursor, but it does not affect the selector, sort criteria, or any published fields. Ignore it!
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "update", id: "ddd", {$set: {game: "dominion"}}}
This is a document not currently in the cursor. This change is to a field from the selector, but it can't make it true. Ignore it!
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avital", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "update", id: "xxx", {$set: {user: "avi"}}}
Invoke changed("xxx", {user: "avi"}).
Cache is now:
{_id: "xxx", user: "avi", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "xxx", user: "avi", score: 150}
{_id: "yyy", user: "naomi", score: 140}
{_id: "zzz", user: "slava", score: 130}
Oplog says:
{op: "insert", id: "bbb", {user: "glasser", game: "carrom", score: 200}}
Matches and sorts at the top!Invoke added("bbb", {user: "glasser", score: 200}) and removed("zzz").
Cache is now:
{_id: "bbb", user: "glasser", score: 200}
{_id: "xxx", user: "avi", score: 150}
{_id: "yyy", user: "naomi", score: 140}
Scores.find({game: "carrom"}, {sort: {score: -1}, limit: 3, fields: {score: 1, user: 1}})
Cache is:
{_id: "bbb", user: "glasser", score: 200}
{_id: "xxx", user: "avi", score: 150}
{_id: "yyy", user: "naomi", score: 140}
Oplog says:
{op: "update", id: "eee", {$set: {score: 500}}}
This matches if "eee" has game: "carrom". We have to fetch doc "eee" from Mongo and check.If it does, invoke added("eee", {user: "emily", score: 500}) and removed("yyy"). Otherwise, do nothing.
Any questions?