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};