| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- "use strict";
- /**
- * A $setissubset pipeline expression.
- * @see evaluateInternal
- * @class SetIsSubsetExpression
- * @namespace mungedb-aggregate.pipeline.expressions
- * @module mungedb-aggregate
- * @constructor
- **/
- var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
- this.nargs = 2;
- if (arguments.length !== 2) throw new Error("two args expected");
- base.call(this);
- }, klass = SetIsSubsetExpression,
- base = require("./NaryExpression"),
- proto = klass.prototype = Object.create(base.prototype, {
- constructor: {
- value: klass
- }
- });
- // 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;
- };
- var Optimized = function Optimized(cachedRhsSet, operands) {
- this.operands = operands;
- this._cachedRhsSet = cachedRhsSet;
- }
- Optimized.prototype = Object.create(SetIsSubsetExpression.prototype, {
- constructor: {
- value: Optimized
- }
- });
- Optimized.prototype.evaluateInternal = function evaluateInternal(vars){
- lhs = this.operands[0].evaluateInternal(vars);
- if (!(lhs instanceof Array)) throw new Error("uassert 17046: both operands of " + this.getOpName() + " must be arrays. Second argument is of type " + typeof lhs);
-
- return setIsSubsetHelper(lhs, this._cachedRhsSet);
- };
- // DEPENDENCIES
- var Value = require("../Value"),
- Expression = require("./Expression"),
- Helpers = require("./Helpers.js");
- // PROTOTYPE MEMBERS
- proto.getOpName = function getOpName() {
- return "$setissubset";
- };
- proto.optimize = function optimize(cachedRhsSet, operands) {
- // perform basic optimizations
- var optimized = base.optimize.call(this);
- // if NaryExpression.optimize() created a new value, return it directly
- if(optimized != this){
- return optimized;
- }
- if (operands[1] instanceof ConstantExpression){
- var ce = 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);
- }
- return optimized;
- };
- /**
- * 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(this.getOpName() + ": object 1 must be an array. Got a(n) " + typeof lhs);
- if (!(rhs instanceof Array)) throw new Error(this.getOpName() + ": object 2 must be an array. Got a(n) " + typeof rhs);
- return setIsSubsetHelper(lhs, Helpers.arrayToSet(rhs));
- };
- /** Register Expression */
- Expression.registerExpression("$setissubset", base.parse(SetIsSubsetExpression));
|