|
|
@@ -8,9 +8,8 @@
|
|
|
* @module mungedb-aggregate
|
|
|
* @constructor
|
|
|
**/
|
|
|
-
|
|
|
var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
|
|
|
-// if (arguments.length !== 2) throw new Error("two args expected");
|
|
|
+ if (arguments.length !== 2) throw new Error("two args expected");
|
|
|
base.call(this);
|
|
|
}, klass = SetIsSubsetExpression,
|
|
|
FixedArityExpression = require("./FixedArityExpressionT")(klass, 2),
|
|
|
@@ -21,90 +20,68 @@ var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-
|
|
|
// DEPENDENCIES
|
|
|
var Value = require("../Value"),
|
|
|
- Expression = require("./Expression"),
|
|
|
- Helpers = require("./Helpers");
|
|
|
+ Expression = require("./Expression");
|
|
|
|
|
|
// PROTOTYPE MEMBERS
|
|
|
proto.getOpName = function getOpName() {
|
|
|
return "$setissubset";
|
|
|
};
|
|
|
|
|
|
+proto.optimize = function optimize(cachedRhsSet, operands) {
|
|
|
|
|
|
-// lhs should be array, rhs should be set (object). See arrayToSet implementation.
|
|
|
-var setIsSubsetHelper = function setIsSubsetHelper(lhs, rhs){
|
|
|
- var lset = Helpers.arrayToSet(lhs);
|
|
|
- rkeys = Object.keys(rhs);
|
|
|
- // do not shortcircuit when lhs.size() > rhs.size()
|
|
|
- // because lhs can have redundant entries
|
|
|
- Object.keys(lset).forEach(function (lkey){
|
|
|
- if (rkeys.indexOf(lkey) < 0){
|
|
|
- return false;
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- return true;
|
|
|
-};
|
|
|
-
|
|
|
-/**
|
|
|
- * Takes 2 arrays. Returns true if the first is a subset of the second. Returns false otherwise.
|
|
|
- * @method evaluateInternal
|
|
|
- **/
|
|
|
-proto.evaluateInternal = function evaluateInternal(vars) {
|
|
|
- var lhs = this.operands[0].evaluateInternal(vars),
|
|
|
- rhs = this.operands[1].evaluateInternal(vars);
|
|
|
-
|
|
|
- if (!(lhs instanceof Array)) throw new Error("Both operands of " + this.getOpName() + ": be arrays. First argument is of type " + typeof lhs);
|
|
|
- if (!(rhs instanceof Array)) throw new Error("Both operands of " + this.getOpName() + ": be arrays. First argument is of type " + typeof rhs);
|
|
|
-
|
|
|
- return setIsSubsetHelper(lhs, Helpers.arrayToSet(rhs));
|
|
|
-};
|
|
|
+// This optimize needs to be done, eventually
|
|
|
|
|
|
+// // perfore basic optimizations
|
|
|
+// intrusive_ptr<Expression> optimized = ExpressionNary::optimize();
|
|
|
|
|
|
+// // if ExpressionNary::optimize() created a new value, return it directly
|
|
|
+// if (optimized.get() != this)
|
|
|
+// return optimized;
|
|
|
|
|
|
-var Optimized = function Optimized(cachedRhsSet, operands) {
|
|
|
- this.operands = operands;
|
|
|
- this._cachedRhsSet = cachedRhsSet;
|
|
|
-}
|
|
|
+// if (ExpressionConstant* ec = dynamic_cast<ExpressionConstant*>(vpOperand[1].get())) {
|
|
|
+// const Value rhs = ec->getValue();
|
|
|
+// uassert(17311, str::stream() << "both operands of $setIsSubset must be arrays. Second "
|
|
|
+// << "argument is of type: " << typeName(rhs.getType()),
|
|
|
+// rhs.getType() == Array);
|
|
|
|
|
|
-Optimized.prototype = Object.create(SetIsSubsetExpression.prototype, {
|
|
|
- constructor: {
|
|
|
- value: Optimized
|
|
|
- }
|
|
|
-});
|
|
|
+// return new Optimized(arrayToSet(rhs), vpOperand);
|
|
|
+// }
|
|
|
|
|
|
-Optimized.prototype.evaluateInternal = function evaluateInternal(vars){
|
|
|
- lhs = this.operands[0].evaluateInternal(vars);
|
|
|
+// return optimized;
|
|
|
|
|
|
- if (!(lhs instanceof Array)) throw new Error("uassert 17310: both operands of " + this.getOpName() + " must be arrays. First argument is of type " + typeof lhs);
|
|
|
-
|
|
|
- return setIsSubsetHelper(lhs, this._cachedRhsSet);
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * Takes 2 arrays. Assigns the second array to the first array.
|
|
|
+ * @method evaluateInternal
|
|
|
+ **/
|
|
|
+proto.evaluateInternal = function evaluateInternal(vars) {
|
|
|
+ var array1 = this.operands[0].evaluateInternal(vars),
|
|
|
+ array2 = this.operands[1].evaluateInternal(vars);
|
|
|
+ if (array1 instanceof Array) throw new Error(this.getOpName() + ": object 1 must be an array");
|
|
|
+ if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
|
|
|
+
|
|
|
+ var sizeOfArray1 = array1.length;
|
|
|
+ var sizeOfArray2 = array2.length;
|
|
|
+ var outerLoop = 0;
|
|
|
+ var innerLoop = 0;
|
|
|
+ for (outerLoop = 0; outerLoop < sizeOfArray1; outerLoop++) {
|
|
|
+ for (innerLoop = 0; innerLoop < sizeOfArray2; innerLoop++) {
|
|
|
+ if (array2[outerLoop] == array1[innerLoop])
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
-proto.optimize = function optimize(cachedRhsSet, operands) {
|
|
|
- // perform basic optimizations
|
|
|
- //var optimized = base.optimize.call(this);
|
|
|
- var optimized = NaryExpression.optimize();
|
|
|
-
|
|
|
- // if NaryExpression.optimize() created a new value, return it directly
|
|
|
- if(optimized != this){
|
|
|
- return optimized;
|
|
|
- }
|
|
|
-
|
|
|
- if (this.operands[1] instanceof ConstantExpression){
|
|
|
- var ce = this.operands[1],
|
|
|
- rhs = ce.getValue();
|
|
|
-
|
|
|
- if (!(rhs instanceof Array)) throw new Error("uassert 17311: both operands of " + this.getOpName() + " must be arrays. Second argument is of type " + typeof rhs);
|
|
|
-
|
|
|
- return new Optimized(Helpers.arrayToSet(rhs), this.operands);
|
|
|
+ /* If the above inner loop was not broken at all then
|
|
|
+ array2[i] is not present in array1[] */
|
|
|
+ if (innerLoop == sizeOfArray2)
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- return optimized;
|
|
|
-
|
|
|
+ /* If we reach here then all elements of array2[]
|
|
|
+ are present in array1[] */
|
|
|
+ return true;
|
|
|
};
|
|
|
|
|
|
/** Register Expression */
|