Переглянути джерело

Refs #3423. Fixed bugs for ElemMatchValueMatchExpression and relatives.

Spencer Rathbun 12 роки тому
батько
коміт
e030428409

+ 6 - 2
lib/pipeline/matcher/ArrayMatchingMatchExpression.js

@@ -4,10 +4,11 @@ var MatchExpression = require('./MatchExpression');
 
 // Autogenerated by cport.py on 2013-09-17 14:37
 var ArrayMatchingMatchExpression = module.exports = function ArrayMatchingMatchExpression(matchType){
+	base.call(this);
 	this._matchType = matchType;
 	// File: expression_array.h lines: 55-55
 	this._elementPath = new ElementPath();
-}, klass = ArrayMatchingMatchExpression, base =  MatchExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+}, klass = ArrayMatchingMatchExpression, base = MatchExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 // DEPENDENCIES
 var errors = require("../../Errors.js"),
@@ -86,8 +87,11 @@ proto._matches = function _matches(doc, path, details){
 			for(var ii = 0, il = item.length; ii < il; ii++){
 				var subitem = item[ii];
 				if (subitem.constructor !== Object) continue;	// can't look for a subfield in a non-object value.
-				if (this._matches(subitem, path.slice(k), details)) // check the item against the rest of the path
+				if (this._matches(subitem, path.slice(k), null)) { // check the item against the rest of the path
+					if (details && details.needRecord())
+						details.setElemMatchKey(ii.toString());
 					return true;
+				}
 			}
 			return false; // checked all items in the array and found no matches
 		}

+ 14 - 20
lib/pipeline/matcher/ComparisonMatchExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 
-var LeafMatchExpression = require('./LeafMatchExpression');
+var LeafMatchExpression = require('./LeafMatchExpression.js');
 var Value = require('../Value');
 
 
@@ -16,7 +16,7 @@ var ComparisonMatchExpression = module.exports = function ComparisonMatchExpress
 proto._rhs = undefined;
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method debugString
  * @param
@@ -55,7 +55,7 @@ proto.debugString = function debugString( level ) { //  StringBuilder& debug, in
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method equivalent
  * @param
@@ -68,20 +68,20 @@ proto.equivalent = function equivalent( other ) {//  const MatchExpression* othe
 //             return false;
 //         const ComparisonMatchExpression* realOther =
 //             static_cast<const ComparisonMatchExpression*>( other );
-// 
+//
 //         return
 //             path() == realOther->path() &&
 //             _rhs.valuesEqual( realOther->_rhs );
 //     }
 	if (other._matchType != this._matchType) { return false; }
-	
-	return this.path() == other.path() && Values.compare(this._rhs,other._rhs);
+
+	return this.path() == other.path() && Value.compare(this._rhs,other._rhs);
 
 };
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method getData
  * @param
@@ -94,7 +94,7 @@ proto.getData = function getData( /*  */ ){
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method getRHS
  * @param
@@ -107,7 +107,7 @@ proto.getRHS = function getRHS( /*  */ ){
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method init
  * @param
@@ -127,19 +127,19 @@ proto.init = function init( path,rhs ) { //  const StringData& path, const BSONE
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method matchesSingleElement
  * @param
  *
  */
 proto.matchesSingleElement = function matchesSingleElement( e ){ //  const BSONElement& e
-// File: expression_leaf.cpp lines: 91-132	
+// File: expression_leaf.cpp lines: 91-132
 	if( typeof(e) != typeof(this._rhs) ){
 		if ((e === null || e === undefined) && (this._rhs ===null || this._rhs === undefined)) {
 			return ["EQ","LTE","GTE"].indexOf(this._matchType) != -1;
 		}
-		
+
 		if (this._rhs.constructor.name in ['MaxKey','MinKey'] ) {
 			return this._matchType != "EQ";
 		}
@@ -151,28 +151,22 @@ proto.matchesSingleElement = function matchesSingleElement( e ){ //  const BSONE
 			return false;
 		}
 	}
-	
+
 	var x = Value.compare( e, this._rhs );
-	
+
 	switch( this._matchType ) {
 		case "LT":
 			return x == -1;
-			break;
 		case "LTE":
 			return x <= 0;
-			break;
 		case "EQ":
 			return x === 0;
-			break;
 		case "GT":
 			return x === 1;
-			break;
 		case "GTE":
 			return x >= 0;
-			break;
 		default:
 			throw new Error("Invalid comparison type evaluated.");
-			break;
 	}
 	return false;
 };

+ 6 - 3
lib/pipeline/matcher/ElemMatchValueMatchExpression.js

@@ -4,7 +4,9 @@ var ArrayMatchingMatchExpression = require('./ArrayMatchingMatchExpression.js');
 
 // Autogenerated by cport.py on 2013-09-17 14:37
 var ElemMatchValueMatchExpression = module.exports = function ElemMatchValueMatchExpression(){
+	base.call(this);
 	this._matchType = 'ELEM_MATCH_VALUE';
+	this._subs = [];
 }, klass = ElemMatchValueMatchExpression, base =  ArrayMatchingMatchExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 // DEPENDENCIES
@@ -81,8 +83,9 @@ proto.getChild = function getChild(i){
  */
 proto.init = function init(path, sub){
 	// File: expression_array.cpp lines: 121-124
-	this.init(path);
-	this.add(sub);
+	this.initPath(path);
+	if (sub)
+		this.add(sub);
 	return {code:ErrorCodes.OK};
 };
 
@@ -100,7 +103,7 @@ proto.matchesArray = function matchesArray(anArray, details){
 
 		if (this._arrayElementMatchesAll(inner)) {
 			if (details && details.needRecord()) {
-				details.setElemMatchKey(inner.fieldName());
+				details.setElemMatchKey(i);
 			}
 			return true;
 		}

+ 5 - 5
lib/pipeline/matcher/GTMatchExpression.js

@@ -1,23 +1,23 @@
 "use strict";
 
-var ComparisonMatchExpression = require('./ComparisonMatchExpression');
+var ComparisonMatchExpression = require('./ComparisonMatchExpression.js');
 
 // Autogenerated by cport.py on 2013-09-17 14:37
 var GTMatchExpression = module.exports = function GTMatchExpression(){
-	this._matchType = 'GT'
+	this._matchType = 'GT';
 }, klass = GTMatchExpression, base =  ComparisonMatchExpression  , proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 /**
- * 
+ *
  * This documentation was automatically generated. Please update when you touch this function.
  * @method shallowClone
  * @param
  *
  */
 proto.shallowClone = function shallowClone( /*  */ ){
-// File: expression_leaf.h lines: 130-133
-        var e = new GTMatchExpression();
+	// File: expression_leaf.h lines: 130-133
+    var e = new GTMatchExpression();
 	e.init( this.path(), this._rhs );
 	return e;
 };

+ 11 - 11
test/lib/pipeline/matcher/ElemMatchValueMatchExpression.js

@@ -53,8 +53,8 @@ module.exports = {
 			assert.strictEqual(op.init("a", gt).code, 'OK');
 			// Directly nested objects are not matched with $elemMatch.  An intervening array is
 			// required.
-			assert.strictEqual(!op.matches({"a":6},null));
-			assert.strictEqual(!op.matches({"a":{"0":6}},null));
+			assert.ok(!op.matches({"a":6},null));
+			assert.ok(!op.matches({"a":{"0":6}},null));
 		},
 
 		"Should match an array scalar": function() {
@@ -64,9 +64,9 @@ module.exports = {
 
 			assert.strictEqual(gt.init("", baseOperand.$gt).code, 'OK');
 			assert.strictEqual(op.init("a", gt).code, 'OK');
-			assert.strictEqual(op.matches({"a":[6]},null));
-			assert.strictEqual(op.matches({"a":[4,6]},null));
-			assert.strictEqual(op.matches({"a":[{},7]},null));
+			assert.ok(op.matches({"a":[6]},null));
+			assert.ok(op.matches({"a":[4,6]},null));
+			assert.ok(op.matches({"a":[{},7]},null));
 		},
 
 		"Should match multiple named values": function() {
@@ -76,8 +76,8 @@ module.exports = {
 
 			assert.strictEqual(gt.init("", baseOperand.$gt).code, 'OK');
 			assert.strictEqual(op.init("a.b", gt).code, 'OK');
-			assert.strictEqual(op.matches({"a":[{"b":[6]}]}, null));
-			assert.strictEqual(op.matches({"a":[{"b":[4]}, {"b":[4,6]}]}, null));
+			assert.ok(op.matches({"a":[{"b":[6]}]}, null));
+			assert.ok(op.matches({"a":[{"b":[4]}, {"b":[4,6]}]}, null));
 		},
 
 		"ElemMatchKey should return the appropriate values": function() {
@@ -89,15 +89,15 @@ module.exports = {
 			assert.strictEqual(gt.init("", baseOperand.$gt).code, 'OK');
 			assert.strictEqual(op.init("a.b", gt).code, 'OK');
 			details.requestElemMatchKey();
-			assert.strictEqual(!op.matches({}, details));
+			assert.ok(!op.matches({}, details));
 			assert.ok(!details.hasElemMatchKey());
-			assert.strictEqual(!op.matches({"a":{"b":[2]}}, details));
+			assert.ok(!op.matches({"a":{"b":[2]}}, details));
 			assert.ok(!details.hasElemMatchKey());
-			assert.strictEqual(op.matches({"a":{"b":[3,7]}}, details));
+			assert.ok(op.matches({"a":{"b":[3,7]}}, details));
 			assert.ok(details.hasElemMatchKey());
 			// The entry within the $elemMatch array is reported.
 			assert.strictEqual("1", details.elemMatchKey());
-			assert.strictEqual(op.matches({"a":[1, 2, {"b":[3,7]}]}, details));
+			assert.ok(op.matches({"a":[1, 2, {"b":[3,7]}]}, details));
 			assert.ok(details.hasElemMatchKey());
 			// The entry within a parent of the $elemMatch array is reported.
 			assert.strictEqual("2", details.elemMatchKey());