Specifically, in all Underscore "collection" functions which treat their
arguments polymorphically as either "object-like" or "array-like", don't
treat arguments with `x.constructor === Object` as arrays (except for
the 'arguments' object).
Fixes#594. Fixes#1737.
This implies it is not allowed in `observe` either, or in cursors
returned from publish functions, or in cursors used in {{#each}}
Why? observeChanges and DDP publication use the ID as part of the
callback/message, and eliding it completely breaks them. Meteor UI uses
the ID with {{#each}} to properly move nodes around instead of
re-rendering. We could try to allow it for `observe` outside of
{{#each}}, but it would feel somewhat inconsistent.
Previously OplogObserveDriver was only used for selectors which
performed equality checks against scalars. Now that we believe minimongo
to be more robust in the face of more MongoDB edge cases, we use
OplogObserveDriver (if configured) for any selector that minimongo can
compile except those containing $near or $where.
(We still do not use OplogObserveDriver for cursors with skip or limit.)
This lowers the max websocket frame length from 1GB to 64MB.
Note that due to #1648, this may not immediately affect existing
checkouts of meteor (but will get into all release builds).
Now they are methods on a compiled Matcher rather than doing their own
operator parsing from scratch. This means less work is happening for
each oplog entry, and it also localizes knowledge about selector
parsing.
Previously, $near was only used in the absence of a sort specifier; now,
it's also used as a tie-breaker when there is a sort specifier. (Tested:
this matches MongoDB.)
The idea will be that "selector" will always mean the EJSON
representation of a selector, and "matcher" will be some compiled
form (whether Minimongo.Matcher or the various lambdas that make it up)
Now selectors don't have a link to the internals of the cursor; instead,
Selector.documentMatches() return values can include a 'distance' field. (This is
the dress rehearsal for also adding an 'arrayIndex' field.)
Contexts that run selectors and may need to sort later now explicitly
keep around a distances IdMap. Specifically, the handles associated with
observeChanges calls each have a distances IdMap, and the _getRawObjects
call has a temporary one (which might alias one of the
observeChanges-related ones if it's being called from observeChanges,
either for the initial query or to re-compute).
Implement branching for $near (not quite the way Mongo does it, but
better than nothing)
That was the last $operator to be moved to the new model, so I could
delete a lot of obsolete stuff.
Instead of having a semi-implicit dependency on the cursor, specify
distances explicitly when "instantiating" the comparator.
The next refactoring will remove _distance from cursor entirely.
Fixes two incompatibilities:
- {$exists: false} did the wrong logic when there were multiple branches
(we (poorly) special-cased $not and $nin but not this negative case)
- No longer require the argument to $exists to be a boolean;
{$exists: 0} and {$exists: 1} should work, eg