Projection functions act on *documents*, not the diffs that are passed
to changed callbacks. For example, a projection `{'a.b': 1}` applied to
the *document* `{a: undefined}` will result in `{}`, but the *diff*
of `{a: undefined}` on a query with that projection should still result
in a `changed` callback with that diff being invoked.
Refactor various parts of minimongo to always have a projectionFn for
each observed query (perhaps a trivial one).
Pass the projection into _diffQueryChanges so that it can apply the
projection *before* taking the diff, in the two cases in Minimongo which
use _diffQueryChanges instead of direct application. (We could instead
make the query's results and resultsSnapshot be projected, but Minimongo
currently relies on the fact that these data structures alias the
documents stored in the collection.)
Stop applying the projection to the diffs in changed via
wrapCallback. (We could still use wrapCallback to apply the projection
for added/addedBefore calls, but it seems more consistent to use the
same mechanisms for added that we use for changed.
Fixes#3800. Fixes#2254. Fixes#3571.
This change actually introduces another layer of projections before diffing, in
addition to more projection after the diffing, on the result.
I didn't figure out why, but the tests fail if you remove either of them.
Adds tests. Fixes#2254.
LocalCollection.wrapTransform is idempotent, so it's OK to doubly-wrap
them, but it's slightly more efficient to notice that a transform has
already been wrapped and not re-wrap it.
(One place where we doubly-wrap transforms is in SynchronousCursor,
which calls wrapTransform on a transform that probably came from
Mongo.Collection, which also wrapped it.)
Fixes#3623.
The `paused` flag is stored on LocalCollection, but two places in
minimongo looked for it on the `query` object (which represents an
active observeChanges call). In both cases, the bug had no correctness
impact but could have a performance impact.
Bug 1:
`_recomputeResults` (used to calculate changes to skip and limit
queries) tried to avoid calculating the diff if the collection had been
paused (by pauseObservers as part of latency compensation), but it
looked for the `paused` flag in the wrong place and always ran the diff.
This didn't have an effect on correctness (because the wrapped callbacks
on `query` are no-ops when `paused` is set) but did waste time on
unnecessary diffs.
Bug 2:
In `update`, we tried to avoid saving original results for skip/limit
queries if the collection was paused, because we don't actually run the
diff for paused queries. (Well, except for the fact that Bug 1 made us
run the diffs anyway...) But since we checked `query.paused` instead of
`self.paused`, we wasted time cloning the results even if we were
paused.
Reviewed at https://rbcommons.com/s/meteor/r/4/
Mongo 2.4 had the following behavior: if
c.update({_id: 'x'}, {y: 1}, {upsert: 1})
resulted in an insert, it would get a random _id instead of 'x'. (This
only happened when the update was a "replacement" rather than a
"modifier".) We dutifully implemented this behavior in various parts of
Meteor and added tests to prove that it occured.
However, this was actually a bug which got fixed in Mongo 2.6:
https://jira.mongodb.org/browse/SERVER-5289
Since this was regarded by Mongo as a bug (not a backwards-incompatible
change deemed worthy of mention in the Mongo 2.6 release notes), we
should just make Meteor always behave the Mongo 2.6 way, no matter what
version we're on (at least in the aspects where Meteor has its own code
to control this). In other parts of Meteor where the queries are just
getting processed by Mongo, the behavior of this special case will match
Mongo's behavior. If you care strongly about consistent behavior in
this strange edge case, upgrade to Mongo 2.6!
Specifically:
- The minimongo implementation of modifiers loses its special-case code
which drops _id from the modified document during an upsert replace.
- Mongo.Collection.update should only generate a random _id as an
insertedId if the selector doesn't mention one.
- The case of a selector mentioning _id and a *replacement* modifier
not mentioning _id should still count as "known ID" in the
lower-level MongoConnection.update, which means that there's no
reason to use simulated upsert and that we should include it as
insertedId in the return object.
- Various tests of the previous behavior should be changed.
(Note that if this commit is cherry-picked onto 1.0.3.1 (ie, run against
2.4), it would fail, because some of the tested cases end up going to
unsimulated Mongo upsert and assume the 2.6 behavior. That's OK, as
described above.)
Fixes#2278.
Fixes#2817. Regular Expressions in JavaScript keep the state when matching for
the same string. When there are two documents with the same value of the
matching field, the minimongo can incorrectly filter collection because regexp
would return different values on different calls.