瀏覽代碼

EAGLESIX-2651: Set*: use ValueSet instead of Helpers

Kyle P Davis 11 年之前
父節點
當前提交
01583d63d0

+ 0 - 25
lib/pipeline/expressions/Helpers.js

@@ -1,25 +0,0 @@
-var Helpers = module.exports = { //jshint ignore:line
-
-	arrayToSet: function arrayToSet(val) { //NOTE: DEVIATION FROM MONGO: we return an Object of JSON-String to Values
-		if (!(val instanceof Array)) throw new Error("Assertion failure");
-		var array = val;
-
-		var set = {};
-		for (var i = 0, l = array.length; i < l; i++) {
-			var item = array[i],
-				itemHash = JSON.stringify(array[i]);
-			set[itemHash] = item;
-		}
-
-		return set;
-	},
-
-	setToArray: function setToArray(set) {	//TODO: used??
-		var array = [];
-		for (var key in set) {
-			array.push(set[key]);
-		}
-		return array;
-	},
-
-};

+ 4 - 6
lib/pipeline/expressions/SetDifferenceExpression.js

@@ -14,7 +14,7 @@ var SetDifferenceExpression = module.exports = function SetDifferenceExpression(
 
 var Value = require("../Value"),
 	Expression = require("./Expression"),
-	Helpers = require("./Helpers");
+	ValueSet = require("./ValueSet");
 
 proto.evaluateInternal = function evaluateInternal(vars) {
 	var lhs = this.operands[0].evaluateInternal(vars),
@@ -31,16 +31,14 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 		throw new Error("both operands of " + this.getOpName() + " must be arrays. Second " +
 			"argument is of type: " + Value.getType(rhs) + "; uassert code 17049");
 
-	var rhsSet = Helpers.arrayToSet(rhs),
+	var rhsSet = new ValueSet(rhs),
 		lhsArray = lhs,
 		returnVec = [];
 	for (var i = 0, l = lhsArray.length; i < l; ++i) {
 		// rhsSet serves the dual role of filtering out elements that were originally present
 		// in RHS and of eleminating duplicates from LHS
-		var it = lhsArray[i],
-			itHash = JSON.stringify(it);
-		if (!(itHash in rhsSet)) {
-			rhsSet[itHash] = it;
+		var it = lhsArray[i];
+		if (rhsSet.insert(it) !== undefined) {
 			returnVec.push(it);
 		}
 	}

+ 4 - 4
lib/pipeline/expressions/SetEqualsExpression.js

@@ -14,7 +14,7 @@ var SetEqualsExpression = module.exports = function SetEqualsExpression() {
 
 var Value = require("../Value"),
 	Expression = require("./Expression"),
-	Helpers = require("./Helpers");
+	ValueSet = require("./ValueSet");
 
 proto.validateArguments = function validateArguments(args) {
 	if (args.length < 2)
@@ -33,10 +33,10 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 				"argument is of type: " + Value.getType(nextEntry) + "; uassert code 17044");
 
 		if (i === 0) {
-			lhs = Helpers.arrayToSet(nextEntry);
+			lhs = new ValueSet(nextEntry);
 		} else {
-			var rhs = Helpers.arrayToSet(nextEntry);
-			if (Object.keys(lhs).join() !== Object.keys(rhs).join()) {
+			var rhs = new ValueSet(nextEntry);
+			if (!lhs.equals(rhs)) {
 				return false;
 			}
 		}

+ 6 - 6
lib/pipeline/expressions/SetIsSubsetExpression.js

@@ -17,18 +17,18 @@ var Value = require("../Value"),
 	Expression = require("./Expression"),
 	NaryExpression = require("./NaryExpression"),
 	ConstantExpression = require("./ConstantExpression"),
-	Helpers = require("./Helpers");
+	ValueSet = require("./ValueSet");
 
-var setIsSubsetHelper = function setIsSubsetHelper(lhs, rhs) { //NOTE: vector<Value> &lhs, ValueSet &rhs
+function setIsSubsetHelper(lhs, rhs) { //NOTE: vector<Value> &lhs, ValueSet &rhs
 	// do not shortcircuit when lhs.size() > rhs.size()
 	// because lhs can have redundant entries
 	for (var i = 0; i < lhs.length; i++) {
-		if (!(JSON.stringify(lhs[i]) in rhs)) {
+		if (!rhs.has(lhs[i])) {
 			return false;
 		}
 	}
 	return true;
-};
+}
 
 proto.evaluateInternal = function evaluateInternal(vars) {
 	var lhs = this.operands[0].evaluateInternal(vars),
@@ -41,7 +41,7 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 		throw new Error("both operands of " + this.getOpName() + ": must be arrays. Second " +
 			"argument is of type " + Value.getType(rhs) + "; code 17042");
 
-	return setIsSubsetHelper(lhs, Helpers.arrayToSet(rhs));
+	return setIsSubsetHelper(lhs, new ValueSet(rhs));
 };
 
 
@@ -83,7 +83,7 @@ proto.optimize = function optimize(cachedRhsSet, operands) { //jshint ignore:lin
 			throw new Error("both operands of " + this.getOpName() + " must be arrays. Second " +
 				"argument is of type " + Value.getType(rhs) + "; uassert code 17311");
 
-		return new Optimized(Helpers.arrayToSet(rhs), this.operands);
+		return new Optimized(new ValueSet(rhs), this.operands);
 	}
 
 	return optimized;

+ 50 - 0
lib/pipeline/expressions/ValueSet.js

@@ -0,0 +1,50 @@
+var ValueSet = module.exports = function ValueSet(vals) {
+	this.set = {};
+	if (vals instanceof Array)
+		this.insertRange(vals);
+}, klass = ValueSet, proto = klass.prototype;
+
+proto._getKey = JSON.stringify;
+
+proto.hasKey = function hasKey(key) {
+	return key in this.set;
+};
+
+proto.has = function has(val) {
+	return this._getKey(val) in this.set;
+};
+
+proto.insert = function insert(val) {
+	var valKey = this._getKey(val);
+	if (!this.hasKey(valKey)) {
+		this.set[valKey] = val;
+		return valKey;
+	}
+	return undefined;
+};
+
+proto.insertRange = function insertRange(vals) {
+	var results = [];
+	for (var i = 0, l = vals.length; i < l; i++)
+		results.push(this.insert(vals[i]));
+	return results;
+};
+
+proto.equals = function equals(other) {
+	for (var key in this.set) {
+		if (!other.hasKey(key))
+			return false;
+	}
+	for (var otherKey in other.set) {
+		if (!this.hasKey(otherKey))
+			return false;
+	}
+	return true;
+};
+
+proto.values = function values() {
+	var vals = [];
+	for (var key in this.set)
+		vals.push(this.set[key]);
+	return vals;
+};