minimongo: support semi-logical $elemMatch

ie, a document with some logical operator and some equality in an
elemMatch.

eg: {a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}}

Fixes #1875.
This commit is contained in:
David Glasser
2014-02-28 23:12:36 -08:00
parent 3ebc9aba60
commit bd05fdb2c5
4 changed files with 27 additions and 3 deletions

View File

@@ -3,6 +3,8 @@
* Use "faye-websocket" (0.7.2) npm module instead of "websocket" (1.0.8) for
server-to-server DDP.
* minimongo: Support {a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}} #1875
## v0.7.1.2

View File

@@ -16,7 +16,10 @@ isIndexable = function (x) {
return isArray(x) || isPlainObject(x);
};
isOperatorObject = function (valueSelector) {
// Returns true if this is an object with at least one key and all keys begin
// with $. Unless inconsistentOK is set, throws if some keys begin with $ and
// others don't.
isOperatorObject = function (valueSelector, inconsistentOK) {
if (!isPlainObject(valueSelector))
return false;
@@ -26,7 +29,10 @@ isOperatorObject = function (valueSelector) {
if (theseAreOperators === undefined) {
theseAreOperators = thisIsOperator;
} else if (theseAreOperators !== thisIsOperator) {
throw new Error("Inconsistent operator: " + valueSelector);
if (!inconsistentOK)
throw new Error("Inconsistent operator: " +
JSON.stringify(valueSelector));
theseAreOperators = false;
}
});
return !!theseAreOperators; // {} has no operators

View File

@@ -820,6 +820,12 @@ Tinytest.add("minimongo - selector_compiler", function (test) {
nomatch({$or: [{a: 2}, {a: 3}], b: 2}, {a: 1, b: 2});
nomatch({$or: [{a: 1}, {a: 2}], b: 3}, {a: 1, b: 2});
// Combining $or with equality
match({x: 1, $or: [{a: 1}, {b: 1}]}, {x: 1, b: 1});
match({$or: [{a: 1}, {b: 1}], x: 1}, {x: 1, b: 1});
nomatch({x: 1, $or: [{a: 1}, {b: 1}]}, {b: 1});
nomatch({x: 1, $or: [{a: 1}, {b: 1}]}, {x: 1});
// $or and $lt, $lte, $gt, $gte
match({$or: [{a: {$lte: 1}}, {a: 2}]}, {a: 1});
nomatch({$or: [{a: {$lt: 1}}, {a: 2}]}, {a: 1});
@@ -1103,6 +1109,16 @@ Tinytest.add("minimongo - selector_compiler", function (test) {
nomatch({a: {$elemMatch: {x: 5}}}, {a: {x: 5}});
match({a: {$elemMatch: {0: {$gt: 5, $lt: 9}}}}, {a: [[6]]});
match({a: {$elemMatch: {'0.b': {$gt: 5, $lt: 9}}}}, {a: [[{b:6}]]});
match({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},
{a: [{x: 1, b: 1}]});
match({a: {$elemMatch: {$or: [{a: 1}, {b: 1}], x: 1}}},
{a: [{x: 1, b: 1}]});
nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},
{a: [{b: 1}]});
nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},
{a: [{x: 1}]});
nomatch({a: {$elemMatch: {x: 1, $or: [{a: 1}, {b: 1}]}}},
{a: [{x: 1}, {b: 1}]});
// $comment
match({a: 5, $comment: "asdf"}, {a: 5});

View File

@@ -653,7 +653,7 @@ var ELEMENT_OPERATORS = {
throw Error("$elemMatch need an object");
var subMatcher, isDocMatcher;
if (isOperatorObject(operand)) {
if (isOperatorObject(operand, true)) {
subMatcher = compileValueSelector(operand, matcher);
isDocMatcher = false;
} else {