| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- "use strict";
- var MapExpression = module.exports = function MapExpression(varName, varId, input, each){
- if (arguments.length !== 4) throw new Error(klass.name + ": args expected: varName, varId, input, each");
- this._varName = varName;
- this._varId = varId;
- this._input = input;
- this._each = each;
- }, klass = MapExpression, Expression = require("./Expression"), base = Expression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
- var Value = require("../Value"),
- Variables = require("./Variables");
- klass.parse = function parse(expr, vpsIn) {
- // if (!(exprFieldName)) throw new Error("Assertion failure"); //NOTE: DEVIATION FROM MONGO: we do not have exprFieldName here
- if (Value.getType(expr) !== "Object") {
- throw new Error("$map only supports an object as it's argument; uassert code 16878");
- }
- // "in" must be parsed after "as" regardless of BSON order
- var inputElem,
- asElem,
- inElem,
- args = expr;
- for (var argFieldName in args) {
- var arg = args[argFieldName];
- if (argFieldName === "input") {
- inputElem = arg;
- } else if (argFieldName === "as") {
- asElem = arg;
- } else if (argFieldName === "in") {
- inElem = arg;
- } else {
- throw new Error("Unrecognized parameter to $map: " + argFieldName + "; uassert code 16879");
- }
- }
- if (!inputElem) throw new Error("Missing 'input' parameter to $map; uassert code 16880");
- if (!asElem) throw new Error("Missing 'as' parameter to $map; uassert code 16881");
- if (!inElem) throw new Error("Missing 'in' parameter to $map; uassert code 16882");
- // parse "input"
- var input = Expression.parseOperand(inputElem, vpsIn); // only has outer vars
- // parse "as"
- var vpsSub = vpsIn, // vpsSub gets our vars, vpsIn doesn't.
- varName = asElem;
- Variables.uassertValidNameForUserWrite(varName);
- var varId = vpsSub.defineVariable(varName);
- // parse "in"
- var inExpr = Expression.parseOperand(inElem, vpsSub); // has access to map variable
- return new MapExpression(varName, varId, input, inExpr);
- };
- proto.optimize = function optimize() {
- // TODO handle when _input is constant
- this._input = this._input.optimize();
- this._each = this._each.optimize();
- return this;
- };
- proto.serialize = function serialize(explain) {
- return {
- $map: {
- input: this._input.serialize(explain),
- as: this._varName,
- in : this._each.serialize(explain)
- }
- };
- };
- proto.evaluateInternal = function evaluateInternal(vars) {
- // guaranteed at parse time that this isn't using our _varId
- var inputVal = this._input.evaluateInternal(vars);
- if (inputVal === null || inputVal === undefined)
- return null;
- if (!(inputVal instanceof Array)){
- throw new Error("input to $map must be an Array not " +
- Value.getType(inputVal) + "; uassert code 16883");
- }
- if (inputVal.length === 0)
- return inputVal;
- var output = new Array(inputVal.length);
- for (var i = 0, l = inputVal.length; i < l; i++) {
- vars.setValue(this._varId, inputVal[i]);
- var toInsert = this._each.evaluateInternal(vars);
- if (toInsert === undefined)
- toInsert = null; // can't insert missing values into array
- output[i] = toInsert;
- }
- return output;
- };
- proto.addDependencies = function addDependencies(deps, path) { //jshint ignore:line
- this._input.addDependencies(deps);
- this._each.addDependencies(deps);
- return deps;
- };
- Expression.registerExpression("$map", klass.parse);
|