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