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

Fixes #988 Added AddToSetAccumulator

http://source.rd.rcg.local/trac/eagle6/changeset/1316/Eagle6_SVN
Adam Bell 12 роки тому
батько
коміт
7890fbb389

+ 49 - 0
lib/pipeline/accumulators/AddToSetAccumulator.js

@@ -0,0 +1,49 @@
+var sha3 = require('sha3'),
+	AddToSetAccumulator = module.exports = (function(){
+
+	// Constructor
+	var klass = module.exports = function AddToSetAccumulator(){
+		this.set = {};
+		base.call(this);
+	}, Accumulator = require("./Accumulator"), base = Accumulator, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+
+	proto.evaluate = function evaluate(doc){
+		if(this.operands.length != 1) throw new Error("this should never happen");
+		var v = this.operands[0].evaluate(doc);
+		if(v)
+			this.set[this._getHashForObject(v)] = v; 
+	
+		return null;
+	};
+
+	proto._getHashForObject = function _getHashForObject(obj){ 
+		// TODO: This uses JSON.stringify which is going to be really slow for any signficant amount of data
+		// Need to figure out a better way to do hasing in Javascript for objects
+		var d = new sha3.SHA3Hash();
+		d.update(JSON.stringify(obj));
+		return d.digest('hex');
+	};
+
+	proto.getValue = function getValue(){
+		var values = [], n = 0;
+		for(var key in this.set){
+			if(this.set.hasOwnProperty(key)) values[n++] = this.set[key];
+		}
+		return values;
+	};
+
+	proto.getOpName = function getOpName(){
+		return "$addToSet";
+	};
+
+	return klass;
+
+})();
+
+
+
+
+
+
+

+ 2 - 1
package.json

@@ -23,7 +23,8 @@
 		"alteration"
 	],
 	"dependencies": {
-		"stream-utils":"*"
+		"stream-utils":"*",
+		"sha3":"*"
 	},
 	"devDependencies": {
 		"mocha": "*",

+ 125 - 0
test/lib/pipeline/accumulators/AddToSetAccumulator.js

@@ -0,0 +1,125 @@
+
+var assert = require("assert"),
+	AddToSetAccumulator = require("../../../../lib/pipeline/accumulators/AddToSetAccumulator"),
+	FieldPathExpression = require("../../../../lib/pipeline/expressions/FieldPathExpression");
+
+
+function createAccumulator(){
+	var accumulator = new AddToSetAccumulator();
+	accumulator.addOperand(new FieldPathExpression("b") );
+	return accumulator;
+}
+
+
+module.exports = {
+
+	"AddToSetAccumulator": {
+
+		"constructor()": {
+
+			"should not throw Error when constructing without args": function testConstructor(){
+				assert.doesNotThrow(function(){
+					new AddToSetAccumulator();
+				});
+			}
+
+		},
+
+		"#getOpName()": {
+
+			"should return the correct op name; $addToSet": function testOpName(){
+				assert.strictEqual(new AddToSetAccumulator().getOpName(), "$addToSet");
+			}
+
+		},
+
+		"#evaluate()": {
+
+			"should evaluate no documents": function testStuff(){
+				var accumulator = createAccumulator();
+				accumulator.evaluate();
+				assert.deepEqual(accumulator.getValue(), []);
+			},
+
+
+			"should evaluate one document and return an set of 1: [1]": function testStuff(){
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:1});
+				assert.deepEqual(accumulator.getValue(), [1]);
+			},
+
+			"should evaluate two documents with the same value and return a set of 1: [1]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:1});
+				accumulator.evaluate({b:1});
+				assert.deepEqual(accumulator.getValue(), [1]);
+			},
+
+			"should evaluate two documents with the same objects as values and return a set of 1: [{foo:'bar'}]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:{foo:"bar"}});
+				accumulator.evaluate({b:{foo:"bar"}});
+				assert.deepEqual(accumulator.getValue(), [{foo:"bar"}]);
+			},
+
+
+			"should evaluate two documents with the same arrays as values and return a set of 1: [[1,2,3]]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:[1,2,3]});
+				accumulator.evaluate({b:[1,2,3]});
+				assert.deepEqual(accumulator.getValue(), [[1,2,3]]);
+			},
+
+
+			"should evaluate two documents with different values and return a set of 2: [1,2]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:1});
+				accumulator.evaluate({b:2});
+				assert.deepEqual(accumulator.getValue(), [1,2]);
+			},
+
+			"should evaluate two documents with the different objects as values and return a set of 2: [{foo:'bar'},{foo:'baz'}]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:{foo:"bar"}});
+				accumulator.evaluate({b:{foo:"baz"}});
+				assert.deepEqual(accumulator.getValue(), [{foo:"bar"},{foo:"baz"}]);
+			},
+
+
+			"should evaluate two documents with the different arrays as values and return a set of 1: [[1,2,3], [1,2]]": function testStuff(){
+
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:[1,2,3]});
+				accumulator.evaluate({b:[1,2]});
+				assert.deepEqual(accumulator.getValue(), [[1,2,3], [1,2]]);
+			},
+
+
+
+			"should evaluate one document with null and one document with a value and return an set of 1: [1]": function testStuff(){
+				var accumulator = createAccumulator();
+				accumulator.evaluate({b:1});
+				accumulator.evaluate({b:null});
+				assert.deepEqual(accumulator.getValue(), [1]);
+			}
+
+		}
+
+	}
+
+};
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
+
+
+
+
+
+
+
+