arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/mongoose/lib/services/setDefaultsOnInsert.js
node_modules/mongoose/lib/services/setDefaultsOnInsert.jsRaw
  1'use strict';
  2
  3var flatten = require('./common').flatten;
  4var modifiedPaths = require('./common').modifiedPaths;
  5
  6/**
  7 * Applies defaults to update and findOneAndUpdate operations.
  8 *
  9 * @param {Query} query
 10 * @param {Schema} schema
 11 * @param {Object} castedDoc
 12 * @param {Object} options
 13 * @method setDefaultsOnInsert
 14 * @api private
 15 */
 16
 17module.exports = function(query, schema, castedDoc, options) {
 18  var keys = Object.keys(castedDoc || {});
 19  var updatedKeys = {};
 20  var updatedValues = {};
 21  var numKeys = keys.length;
 22  var hasDollarUpdate = false;
 23  var modified = {};
 24
 25  for (var i = 0; i < numKeys; ++i) {
 26    if (keys[i].charAt(0) === '$') {
 27      modifiedPaths(castedDoc[keys[i]], '', modified);
 28      var flat = flatten(castedDoc[keys[i]]);
 29      var paths = Object.keys(flat);
 30      var numPaths = paths.length;
 31      for (var j = 0; j < numPaths; ++j) {
 32        var updatedPath = paths[j].replace('.$.', '.0.');
 33        updatedPath = updatedPath.replace(/\.\$$/, '.0');
 34        if (keys[i] === '$set' || keys[i] === '$setOnInsert') {
 35          updatedValues[updatedPath] = flat[paths[j]];
 36        } else if (keys[i] === '$unset') {
 37          updatedValues[updatedPath] = undefined;
 38        }
 39        updatedKeys[updatedPath] = true;
 40      }
 41      hasDollarUpdate = true;
 42    }
 43  }
 44
 45  if (!hasDollarUpdate) {
 46    modifiedPaths(castedDoc, '', modified);
 47    updatedValues = flatten(castedDoc);
 48    updatedKeys = Object.keys(updatedValues);
 49  }
 50
 51  if (options && options.upsert) {
 52    paths = Object.keys(query._conditions);
 53    numPaths = keys.length;
 54    for (i = 0; i < numPaths; ++i) {
 55      var path = paths[i];
 56      var condition = query._conditions[path];
 57      if (condition && typeof condition === 'object') {
 58        var conditionKeys = Object.keys(condition);
 59        var numConditionKeys = conditionKeys.length;
 60        var hasDollarKey = false;
 61        for (j = 0; j < numConditionKeys; ++j) {
 62          if (conditionKeys[j].charAt(0) === '$') {
 63            hasDollarKey = true;
 64            break;
 65          }
 66        }
 67        if (hasDollarKey) {
 68          continue;
 69        }
 70      }
 71      updatedKeys[path] = true;
 72      modified[path] = true;
 73    }
 74
 75    if (options.setDefaultsOnInsert) {
 76      schema.eachPath(function(path, schemaType) {
 77        if (path === '_id') {
 78          // Ignore _id for now because it causes bugs in 2.4
 79          return;
 80        }
 81        if (schemaType.$isSingleNested) {
 82          // Only handle nested schemas 1-level deep to avoid infinite
 83          // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
 84          schemaType.schema.eachPath(function(_path, _schemaType) {
 85            if (path === '_id') {
 86              // Ignore _id for now because it causes bugs in 2.4
 87              return;
 88            }
 89
 90            var def = _schemaType.getDefault(null, true);
 91            if (!modified[path + '.' + _path] && typeof def !== 'undefined') {
 92              castedDoc = castedDoc || {};
 93              castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
 94              castedDoc.$setOnInsert[path + '.' + _path] = def;
 95              updatedValues[path + '.' + _path] = def;
 96            }
 97          });
 98        } else {
 99          var def = schemaType.getDefault(null, true);
100          if (!modified[path] && typeof def !== 'undefined') {
101            castedDoc = castedDoc || {};
102            castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
103            castedDoc.$setOnInsert[path] = def;
104            updatedValues[path] = def;
105          }
106        }
107      });
108    }
109  }
110
111  return castedDoc;
112};