|
|
'use strict';
var flatten = require('./common').flatten; var modifiedPaths = require('./common').modifiedPaths;
/** * Applies defaults to update and findOneAndUpdate operations. * * @param {Query} query * @param {Schema} schema * @param {Object} castedDoc * @param {Object} options * @method setDefaultsOnInsert * @api private */
module.exports = function(query, schema, castedDoc, options) { var keys = Object.keys(castedDoc || {}); var updatedKeys = {}; var updatedValues = {}; var numKeys = keys.length; var hasDollarUpdate = false; var modified = {};
for (var i = 0; i < numKeys; ++i) { if (keys[i].charAt(0) === '$') { modifiedPaths(castedDoc[keys[i]], '', modified); var flat = flatten(castedDoc[keys[i]]); var paths = Object.keys(flat); var numPaths = paths.length; for (var j = 0; j < numPaths; ++j) { var updatedPath = paths[j].replace('.$.', '.0.'); updatedPath = updatedPath.replace(/\.\$$/, '.0'); if (keys[i] === '$set' || keys[i] === '$setOnInsert') { updatedValues[updatedPath] = flat[paths[j]]; } else if (keys[i] === '$unset') { updatedValues[updatedPath] = undefined; } updatedKeys[updatedPath] = true; } hasDollarUpdate = true; } }
if (!hasDollarUpdate) { modifiedPaths(castedDoc, '', modified); updatedValues = flatten(castedDoc); updatedKeys = Object.keys(updatedValues); }
if (options && options.upsert) { paths = Object.keys(query._conditions); numPaths = keys.length; for (i = 0; i < numPaths; ++i) { var path = paths[i]; var condition = query._conditions[path]; if (condition && typeof condition === 'object') { var conditionKeys = Object.keys(condition); var numConditionKeys = conditionKeys.length; var hasDollarKey = false; for (j = 0; j < numConditionKeys; ++j) { if (conditionKeys[j].charAt(0) === '$') { hasDollarKey = true; break; } } if (hasDollarKey) { continue; } } updatedKeys[path] = true; modified[path] = true; }
if (options.setDefaultsOnInsert) { schema.eachPath(function(path, schemaType) { if (path === '_id') { // Ignore _id for now because it causes bugs in 2.4
return; } if (schemaType.$isSingleNested) { // Only handle nested schemas 1-level deep to avoid infinite
// recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
schemaType.schema.eachPath(function(_path, _schemaType) { if (path === '_id') { // Ignore _id for now because it causes bugs in 2.4
return; }
var def = _schemaType.getDefault(null, true); if (!modified[path + '.' + _path] && typeof def !== 'undefined') { castedDoc = castedDoc || {}; castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; castedDoc.$setOnInsert[path + '.' + _path] = def; updatedValues[path + '.' + _path] = def; } }); } else { var def = schemaType.getDefault(null, true); if (!modified[path] && typeof def !== 'undefined') { castedDoc = castedDoc || {}; castedDoc.$setOnInsert = castedDoc.$setOnInsert || {}; castedDoc.$setOnInsert[path] = def; updatedValues[path] = def; } } }); } }
return castedDoc; };
|