This matches the server behavior. It's dangerously easy to accidently
pass a falsey selector to remove. To really remove all documents in a
collection, explicitly pass the {} selector.
Publish now comes in three flavors:
* Bare metal API: Meteor.publish(name, func).
Server will call func(sub, params) each time a client subscribes to
"name" (with supplied "params"), or if "name" is null, each time a new
client connects (autopublish). "sub" is a Subscription object, which
supplies sub.set(), sub.unset(), sub.satisfies(), and sub.flush()
methods to emit DDP data messages. func() should register a cleanup
function with sub.onStop(), which will be called when client unsubs.
To react to database changes, use Collection.observe(). Publish
functions that are not database backed may use some other mechanism
(setInterval?) to schedule calls to sub.set().
* publishCursor API:
If func() *returns* a Cursor, server will automatically publish all
results from that cursor as the collection with the same name as the
cursor's underlying Mongo collection. For example:
Meteor.publish('top10', function (sub, params) {
return Players.find({}, {sort: {score: -1}, limit: 10});
});
will define a 'top10' publish that is always the top 10 scoring
players, published to the 'players' collection on each subscribing
client.
* autopublish
When the autopublish package is loaded, all Collections defined on the
server will automatically be published, in their entirety, to each
connected client. Clients need not call Meteor.subscribe(). Calls to
publish() will emit a warning message, since they are superflous. To
disable autopublish, run "meteor remove autopublish".
* remove() removes all documents in collection (previously, had to
explicitly pass {} selector to MM).
* update() requires {multi: true} to update multiple documents.
Previously we defaulted to true, now multi defaults to false.
In Livedata and Minimongo, make falsey selectors match no documents,
instead of all documents. Same for {_id: undefined}. This is a
departure from most MongoDB drivers, but offers a safety belt around
selectors that are rarely useful and easy to accidentally create
programmatically.
For remove(), also protect against accidentally destroying an entire
collection when passing no args. To empty a collection, pass the
wildcard selector explicitly: foo.remove({});
For find(), keep the standard mongo behavior of returning all documents
when no selector is passed in by explicitly checking arguments.length.
This change also makes typical read cases cleaner, allowing:
x = foo.findOne(Session.get('foo_id'));
instead of
x = Session.get('foo_id') && foo.findOne(Session.get('foo_id'));
The new Collection API separates query handles from result sets. It
allows template iterators to only redraw changed objects instead of
entire result sets. This implementation also sets the stage for
minimongo indexes and better invalidation performance.
collection.find() now returns a Collection.Query handle. To retrieve
results we provide these methods on Collection.Query:
Iterators (encouraged way to access results):
* query.forEach(function (obj) { ... });
* results = query.map(function (obj) { ... });
Cursor-based retrieval (iterators are built on fetch):
* docs = query.fetch(maxlen); // return next [maxlen] (all) docs.
* doc = query.get(skip); // return next doc, skipping [skip] (0) docs.
Counter:
* length = query.count(); // number of results in query.
Live queries (replaces findLive):
* live_handle = query.observe({added: function (obj, idx) { ... },
removed: function (id, idx) { ... },
changed: function (obj, idx) { ... },
moved: function (obj, old_idx, new_idx) { ... }});
Convenience finders:
* doc = collection.findOne({color: 'red'});
* doc = collection.findOne(id_val);
On the client, calling forEach(), map(), fetch(), get(), or findOne()
inside an invalidation context will register a dependency on the entire
query result. Any change to any objects invalidates the context.
Calling count() inside an invalidation context will register a
dependency that only triggers if objects enter or leave the result set.
Calling observe() does not register a dependency.
on the client, minimongo defines (and relies on) Collection.random()
and Collection.uuid() to generate _id values.
on the server, livedata defines (and relies on) Sky.random()
and Sky.uuid() for the same.
random/uuid code is duplicated, as it was before.