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.
 
 
 
 
 

118 lines
3.4 KiB

'use strict';
var modifiedPaths = require('./common').modifiedPaths;
/**
* Applies defaults to update and findOneAndUpdate operations.
*
* @param {Object} filter
* @param {Schema} schema
* @param {Object} castedDoc
* @param {Object} options
* @method setDefaultsOnInsert
* @api private
*/
module.exports = function(filter, schema, castedDoc, options) {
var keys = Object.keys(castedDoc || {});
var updatedKeys = {};
var updatedValues = {};
var numKeys = keys.length;
var hasDollarUpdate = false;
var modified = {};
if (options && options.upsert) {
for (var i = 0; i < numKeys; ++i) {
if (keys[i].charAt(0) === '$') {
modifiedPaths(castedDoc[keys[i]], '', modified);
hasDollarUpdate = true;
}
}
if (!hasDollarUpdate) {
modifiedPaths(castedDoc, '', modified);
}
var paths = Object.keys(filter);
var numPaths = paths.length;
for (i = 0; i < numPaths; ++i) {
var path = paths[i];
var condition = filter[path];
if (condition && typeof condition === 'object') {
var conditionKeys = Object.keys(condition);
var numConditionKeys = conditionKeys.length;
var hasDollarKey = false;
for (var j = 0; j < numConditionKeys; ++j) {
if (conditionKeys[j].charAt(0) === '$') {
hasDollarKey = true;
break;
}
}
if (hasDollarKey) {
continue;
}
}
updatedKeys[path] = true;
modified[path] = true;
}
if (options && options.overwrite && !hasDollarUpdate) {
// Defaults will be set later, since we're overwriting we'll cast
// the whole update to a document
return castedDoc;
}
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 (!isModified(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 (!isModified(modified, path) && typeof def !== 'undefined') {
castedDoc = castedDoc || {};
castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
castedDoc.$setOnInsert[path] = def;
updatedValues[path] = def;
}
}
});
}
}
return castedDoc;
};
function isModified(modified, path) {
if (modified[path]) {
return true;
}
var sp = path.split('.');
var cur = sp[0];
for (var i = 0; i < sp.length; ++i) {
if (modified[cur]) {
return true;
}
cur += '.' + sp[i];
}
return false;
}