You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					365 lines
				
				12 KiB
			
		
		
			
		
	
	
					365 lines
				
				12 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								 * Module dependencies.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const CastError = require('./error/cast');
							 | 
						||
| 
								 | 
							
								const StrictModeError = require('./error/strict');
							 | 
						||
| 
								 | 
							
								const Types = require('./schema/index');
							 | 
						||
| 
								 | 
							
								const castTextSearch = require('./schema/operators/text');
							 | 
						||
| 
								 | 
							
								const get = require('./helpers/get');
							 | 
						||
| 
								 | 
							
								const getConstructorName = require('./helpers/getConstructorName');
							 | 
						||
| 
								 | 
							
								const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
							 | 
						||
| 
								 | 
							
								const isOperator = require('./helpers/query/isOperator');
							 | 
						||
| 
								 | 
							
								const util = require('util');
							 | 
						||
| 
								 | 
							
								const isObject = require('./helpers/isObject');
							 | 
						||
| 
								 | 
							
								const isMongooseObject = require('./helpers/isMongooseObject');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Handles internal casting for query filters.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param {Schema} schema
							 | 
						||
| 
								 | 
							
								 * @param {Object} obj Object to cast
							 | 
						||
| 
								 | 
							
								 * @param {Object} options the query options
							 | 
						||
| 
								 | 
							
								 * @param {Query} context passed to setters
							 | 
						||
| 
								 | 
							
								 * @api private
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								module.exports = function cast(schema, obj, options, context) {
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(obj)) {
							 | 
						||
| 
								 | 
							
								    throw new Error('Query filter must be an object, got an array ', util.inspect(obj));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (obj == null) {
							 | 
						||
| 
								 | 
							
								    return obj;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // bson 1.x has the unfortunate tendency to remove filters that have a top-level
							 | 
						||
| 
								 | 
							
								  // `_bsontype` property. But we should still allow ObjectIds because
							 | 
						||
| 
								 | 
							
								  // `Collection#find()` has a special case to support `find(objectid)`.
							 | 
						||
| 
								 | 
							
								  // Should remove this when we upgrade to bson 4.x. See gh-8222, gh-8268
							 | 
						||
| 
								 | 
							
								  if (obj.hasOwnProperty('_bsontype') && obj._bsontype !== 'ObjectID') {
							 | 
						||
| 
								 | 
							
								    delete obj._bsontype;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (schema != null && schema.discriminators != null && obj[schema.options.discriminatorKey] != null) {
							 | 
						||
| 
								 | 
							
								    schema = getSchemaDiscriminatorByValue(schema, obj[schema.options.discriminatorKey]) || schema;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const paths = Object.keys(obj);
							 | 
						||
| 
								 | 
							
								  let i = paths.length;
							 | 
						||
| 
								 | 
							
								  let _keys;
							 | 
						||
| 
								 | 
							
								  let any$conditionals;
							 | 
						||
| 
								 | 
							
								  let schematype;
							 | 
						||
| 
								 | 
							
								  let nested;
							 | 
						||
| 
								 | 
							
								  let path;
							 | 
						||
| 
								 | 
							
								  let type;
							 | 
						||
| 
								 | 
							
								  let val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  options = options || {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (i--) {
							 | 
						||
| 
								 | 
							
								    path = paths[i];
							 | 
						||
| 
								 | 
							
								    val = obj[path];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (path === '$or' || path === '$nor' || path === '$and') {
							 | 
						||
| 
								 | 
							
								      if (!Array.isArray(val)) {
							 | 
						||
| 
								 | 
							
								        throw new CastError('Array', val, path);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      for (let k = 0; k < val.length; ++k) {
							 | 
						||
| 
								 | 
							
								        if (val[k] == null || typeof val[k] !== 'object') {
							 | 
						||
| 
								 | 
							
								          throw new CastError('Object', val[k], path + '.' + k);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        val[k] = cast(schema, val[k], options, context);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else if (path === '$where') {
							 | 
						||
| 
								 | 
							
								      type = typeof val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (type !== 'string' && type !== 'function') {
							 | 
						||
| 
								 | 
							
								        throw new Error('Must have a string or function for $where');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (type === 'function') {
							 | 
						||
| 
								 | 
							
								        obj[path] = val.toString();
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    } else if (path === '$elemMatch') {
							 | 
						||
| 
								 | 
							
								      val = cast(schema, val, options, context);
							 | 
						||
| 
								 | 
							
								    } else if (path === '$text') {
							 | 
						||
| 
								 | 
							
								      val = castTextSearch(val, path);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (!schema) {
							 | 
						||
| 
								 | 
							
								        // no casting for Mixed types
							 | 
						||
| 
								 | 
							
								        continue;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      schematype = schema.path(path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Check for embedded discriminator paths
							 | 
						||
| 
								 | 
							
								      if (!schematype) {
							 | 
						||
| 
								 | 
							
								        const split = path.split('.');
							 | 
						||
| 
								 | 
							
								        let j = split.length;
							 | 
						||
| 
								 | 
							
								        while (j--) {
							 | 
						||
| 
								 | 
							
								          const pathFirstHalf = split.slice(0, j).join('.');
							 | 
						||
| 
								 | 
							
								          const pathLastHalf = split.slice(j).join('.');
							 | 
						||
| 
								 | 
							
								          const _schematype = schema.path(pathFirstHalf);
							 | 
						||
| 
								 | 
							
								          const discriminatorKey = get(_schematype, 'schema.options.discriminatorKey');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // gh-6027: if we haven't found the schematype but this path is
							 | 
						||
| 
								 | 
							
								          // underneath an embedded discriminator and the embedded discriminator
							 | 
						||
| 
								 | 
							
								          // key is in the query, use the embedded discriminator schema
							 | 
						||
| 
								 | 
							
								          if (_schematype != null &&
							 | 
						||
| 
								 | 
							
								              get(_schematype, 'schema.discriminators') != null &&
							 | 
						||
| 
								 | 
							
								              discriminatorKey != null &&
							 | 
						||
| 
								 | 
							
								              pathLastHalf !== discriminatorKey) {
							 | 
						||
| 
								 | 
							
								            const discriminatorVal = get(obj, pathFirstHalf + '.' + discriminatorKey);
							 | 
						||
| 
								 | 
							
								            if (discriminatorVal != null) {
							 | 
						||
| 
								 | 
							
								              schematype = _schematype.schema.discriminators[discriminatorVal].
							 | 
						||
| 
								 | 
							
								                path(pathLastHalf);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!schematype) {
							 | 
						||
| 
								 | 
							
								        // Handle potential embedded array queries
							 | 
						||
| 
								 | 
							
								        const split = path.split('.');
							 | 
						||
| 
								 | 
							
								        let j = split.length;
							 | 
						||
| 
								 | 
							
								        let pathFirstHalf;
							 | 
						||
| 
								 | 
							
								        let pathLastHalf;
							 | 
						||
| 
								 | 
							
								        let remainingConds;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Find the part of the var path that is a path of the Schema
							 | 
						||
| 
								 | 
							
								        while (j--) {
							 | 
						||
| 
								 | 
							
								          pathFirstHalf = split.slice(0, j).join('.');
							 | 
						||
| 
								 | 
							
								          schematype = schema.path(pathFirstHalf);
							 | 
						||
| 
								 | 
							
								          if (schematype) {
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // If a substring of the input path resolves to an actual real path...
							 | 
						||
| 
								 | 
							
								        if (schematype) {
							 | 
						||
| 
								 | 
							
								          // Apply the casting; similar code for $elemMatch in schema/array.js
							 | 
						||
| 
								 | 
							
								          if (schematype.caster && schematype.caster.schema) {
							 | 
						||
| 
								 | 
							
								            remainingConds = {};
							 | 
						||
| 
								 | 
							
								            pathLastHalf = split.slice(j).join('.');
							 | 
						||
| 
								 | 
							
								            remainingConds[pathLastHalf] = val;
							 | 
						||
| 
								 | 
							
								            obj[path] = cast(schematype.caster.schema, remainingConds, options, context)[pathLastHalf];
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            obj[path] = val;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          continue;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isObject(val)) {
							 | 
						||
| 
								 | 
							
								          // handle geo schemas that use object notation
							 | 
						||
| 
								 | 
							
								          // { loc: { long: Number, lat: Number }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          let geo = '';
							 | 
						||
| 
								 | 
							
								          if (val.$near) {
							 | 
						||
| 
								 | 
							
								            geo = '$near';
							 | 
						||
| 
								 | 
							
								          } else if (val.$nearSphere) {
							 | 
						||
| 
								 | 
							
								            geo = '$nearSphere';
							 | 
						||
| 
								 | 
							
								          } else if (val.$within) {
							 | 
						||
| 
								 | 
							
								            geo = '$within';
							 | 
						||
| 
								 | 
							
								          } else if (val.$geoIntersects) {
							 | 
						||
| 
								 | 
							
								            geo = '$geoIntersects';
							 | 
						||
| 
								 | 
							
								          } else if (val.$geoWithin) {
							 | 
						||
| 
								 | 
							
								            geo = '$geoWithin';
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (geo) {
							 | 
						||
| 
								 | 
							
								            const numbertype = new Types.Number('__QueryCasting__');
							 | 
						||
| 
								 | 
							
								            let value = val[geo];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (val.$maxDistance != null) {
							 | 
						||
| 
								 | 
							
								              val.$maxDistance = numbertype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                val: val.$maxDistance,
							 | 
						||
| 
								 | 
							
								                context: context
							 | 
						||
| 
								 | 
							
								              });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (val.$minDistance != null) {
							 | 
						||
| 
								 | 
							
								              val.$minDistance = numbertype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                val: val.$minDistance,
							 | 
						||
| 
								 | 
							
								                context: context
							 | 
						||
| 
								 | 
							
								              });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (geo === '$within') {
							 | 
						||
| 
								 | 
							
								              const withinType = value.$center
							 | 
						||
| 
								 | 
							
								                  || value.$centerSphere
							 | 
						||
| 
								 | 
							
								                  || value.$box
							 | 
						||
| 
								 | 
							
								                  || value.$polygon;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              if (!withinType) {
							 | 
						||
| 
								 | 
							
								                throw new Error('Bad $within parameter: ' + JSON.stringify(val));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              value = withinType;
							 | 
						||
| 
								 | 
							
								            } else if (geo === '$near' &&
							 | 
						||
| 
								 | 
							
								                typeof value.type === 'string' && Array.isArray(value.coordinates)) {
							 | 
						||
| 
								 | 
							
								              // geojson; cast the coordinates
							 | 
						||
| 
								 | 
							
								              value = value.coordinates;
							 | 
						||
| 
								 | 
							
								            } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') &&
							 | 
						||
| 
								 | 
							
								                value.$geometry && typeof value.$geometry.type === 'string' &&
							 | 
						||
| 
								 | 
							
								                Array.isArray(value.$geometry.coordinates)) {
							 | 
						||
| 
								 | 
							
								              if (value.$maxDistance != null) {
							 | 
						||
| 
								 | 
							
								                value.$maxDistance = numbertype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                  val: value.$maxDistance,
							 | 
						||
| 
								 | 
							
								                  context: context
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              if (value.$minDistance != null) {
							 | 
						||
| 
								 | 
							
								                value.$minDistance = numbertype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                  val: value.$minDistance,
							 | 
						||
| 
								 | 
							
								                  context: context
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              if (isMongooseObject(value.$geometry)) {
							 | 
						||
| 
								 | 
							
								                value.$geometry = value.$geometry.toObject({
							 | 
						||
| 
								 | 
							
								                  transform: false,
							 | 
						||
| 
								 | 
							
								                  virtuals: false
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              value = value.$geometry.coordinates;
							 | 
						||
| 
								 | 
							
								            } else if (geo === '$geoWithin') {
							 | 
						||
| 
								 | 
							
								              if (value.$geometry) {
							 | 
						||
| 
								 | 
							
								                if (isMongooseObject(value.$geometry)) {
							 | 
						||
| 
								 | 
							
								                  value.$geometry = value.$geometry.toObject({ virtuals: false });
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                const geoWithinType = value.$geometry.type;
							 | 
						||
| 
								 | 
							
								                if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) {
							 | 
						||
| 
								 | 
							
								                  throw new Error('Invalid geoJSON type for $geoWithin "' +
							 | 
						||
| 
								 | 
							
								                    geoWithinType + '", must be "Polygon" or "MultiPolygon"');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                value = value.$geometry.coordinates;
							 | 
						||
| 
								 | 
							
								              } else {
							 | 
						||
| 
								 | 
							
								                value = value.$box || value.$polygon || value.$center ||
							 | 
						||
| 
								 | 
							
								                  value.$centerSphere;
							 | 
						||
| 
								 | 
							
								                if (isMongooseObject(value)) {
							 | 
						||
| 
								 | 
							
								                  value = value.toObject({ virtuals: false });
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            _cast(value, numbertype, context);
							 | 
						||
| 
								 | 
							
								            continue;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (schema.nested[path]) {
							 | 
						||
| 
								 | 
							
								          continue;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (options.upsert && options.strict) {
							 | 
						||
| 
								 | 
							
								          if (options.strict === 'throw') {
							 | 
						||
| 
								 | 
							
								            throw new StrictModeError(path);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
							 | 
						||
| 
								 | 
							
								            'schema, strict mode is `true`, and upsert is `true`.');
							 | 
						||
| 
								 | 
							
								        } else if (options.strictQuery === 'throw') {
							 | 
						||
| 
								 | 
							
								          throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
							 | 
						||
| 
								 | 
							
								            'schema and strictQuery is \'throw\'.');
							 | 
						||
| 
								 | 
							
								        } else if (options.strictQuery) {
							 | 
						||
| 
								 | 
							
								          delete obj[path];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (val == null) {
							 | 
						||
| 
								 | 
							
								        continue;
							 | 
						||
| 
								 | 
							
								      } else if (getConstructorName(val) === 'Object') {
							 | 
						||
| 
								 | 
							
								        any$conditionals = Object.keys(val).some(isOperator);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!any$conditionals) {
							 | 
						||
| 
								 | 
							
								          obj[path] = schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								            val: val,
							 | 
						||
| 
								 | 
							
								            context: context
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          const ks = Object.keys(val);
							 | 
						||
| 
								 | 
							
								          let $cond;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          let k = ks.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          while (k--) {
							 | 
						||
| 
								 | 
							
								            $cond = ks[k];
							 | 
						||
| 
								 | 
							
								            nested = val[$cond];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if ($cond === '$not') {
							 | 
						||
| 
								 | 
							
								              if (nested && schematype && !schematype.caster) {
							 | 
						||
| 
								 | 
							
								                _keys = Object.keys(nested);
							 | 
						||
| 
								 | 
							
								                if (_keys.length && isOperator(_keys[0])) {
							 | 
						||
| 
								 | 
							
								                  for (const key in nested) {
							 | 
						||
| 
								 | 
							
								                    nested[key] = schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                      $conditional: key,
							 | 
						||
| 
								 | 
							
								                      val: nested[key],
							 | 
						||
| 
								 | 
							
								                      context: context
							 | 
						||
| 
								 | 
							
								                    });
							 | 
						||
| 
								 | 
							
								                  }
							 | 
						||
| 
								 | 
							
								                } else {
							 | 
						||
| 
								 | 
							
								                  val[$cond] = schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                    $conditional: $cond,
							 | 
						||
| 
								 | 
							
								                    val: nested,
							 | 
						||
| 
								 | 
							
								                    context: context
							 | 
						||
| 
								 | 
							
								                  });
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								              val[$cond] = schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								                $conditional: $cond,
							 | 
						||
| 
								 | 
							
								                val: nested,
							 | 
						||
| 
								 | 
							
								                context: context
							 | 
						||
| 
								 | 
							
								              });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (Array.isArray(val) && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) {
							 | 
						||
| 
								 | 
							
								        const casted = [];
							 | 
						||
| 
								 | 
							
								        const valuesArray = val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for (const _val of valuesArray) {
							 | 
						||
| 
								 | 
							
								          casted.push(schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								            val: _val,
							 | 
						||
| 
								 | 
							
								            context: context
							 | 
						||
| 
								 | 
							
								          }));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        obj[path] = { $in: casted };
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        obj[path] = schematype.castForQueryWrapper({
							 | 
						||
| 
								 | 
							
								          val: val,
							 | 
						||
| 
								 | 
							
								          context: context
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _cast(val, numbertype, context) {
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(val)) {
							 | 
						||
| 
								 | 
							
								    val.forEach(function(item, i) {
							 | 
						||
| 
								 | 
							
								      if (Array.isArray(item) || isObject(item)) {
							 | 
						||
| 
								 | 
							
								        return _cast(item, numbertype, context);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      val[i] = numbertype.castForQueryWrapper({ val: item, context: context });
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    const nearKeys = Object.keys(val);
							 | 
						||
| 
								 | 
							
								    let nearLen = nearKeys.length;
							 | 
						||
| 
								 | 
							
								    while (nearLen--) {
							 | 
						||
| 
								 | 
							
								      const nkey = nearKeys[nearLen];
							 | 
						||
| 
								 | 
							
								      const item = val[nkey];
							 | 
						||
| 
								 | 
							
								      if (Array.isArray(item) || isObject(item)) {
							 | 
						||
| 
								 | 
							
								        _cast(item, numbertype, context);
							 | 
						||
| 
								 | 
							
								        val[nkey] = item;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        val[nkey] = numbertype.castForQuery({ val: item, context: context });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |