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?