Ohm-Management - Projektarbeit B-ME
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.

setDefaultsOnInsert.js 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. 'use strict';
  2. const modifiedPaths = require('./common').modifiedPaths;
  3. /**
  4. * Applies defaults to update and findOneAndUpdate operations.
  5. *
  6. * @param {Object} filter
  7. * @param {Schema} schema
  8. * @param {Object} castedDoc
  9. * @param {Object} options
  10. * @method setDefaultsOnInsert
  11. * @api private
  12. */
  13. module.exports = function(filter, schema, castedDoc, options) {
  14. const keys = Object.keys(castedDoc || {});
  15. const updatedKeys = {};
  16. const updatedValues = {};
  17. const numKeys = keys.length;
  18. const modified = {};
  19. let hasDollarUpdate = false;
  20. options = options || {};
  21. if (!options.upsert || !options.setDefaultsOnInsert) {
  22. return castedDoc;
  23. }
  24. for (let i = 0; i < numKeys; ++i) {
  25. if (keys[i].startsWith('$')) {
  26. modifiedPaths(castedDoc[keys[i]], '', modified);
  27. hasDollarUpdate = true;
  28. }
  29. }
  30. if (!hasDollarUpdate) {
  31. modifiedPaths(castedDoc, '', modified);
  32. }
  33. const paths = Object.keys(filter);
  34. const numPaths = paths.length;
  35. for (let i = 0; i < numPaths; ++i) {
  36. const path = paths[i];
  37. const condition = filter[path];
  38. if (condition && typeof condition === 'object') {
  39. const conditionKeys = Object.keys(condition);
  40. const numConditionKeys = conditionKeys.length;
  41. let hasDollarKey = false;
  42. for (let j = 0; j < numConditionKeys; ++j) {
  43. if (conditionKeys[j].startsWith('$')) {
  44. hasDollarKey = true;
  45. break;
  46. }
  47. }
  48. if (hasDollarKey) {
  49. continue;
  50. }
  51. }
  52. updatedKeys[path] = true;
  53. modified[path] = true;
  54. }
  55. if (options && options.overwrite && !hasDollarUpdate) {
  56. // Defaults will be set later, since we're overwriting we'll cast
  57. // the whole update to a document
  58. return castedDoc;
  59. }
  60. schema.eachPath(function(path, schemaType) {
  61. // Skip single nested paths if underneath a map
  62. const isUnderneathMap = schemaType.path.endsWith('.$*') ||
  63. schemaType.path.indexOf('.$*.') !== -1;
  64. if (schemaType.$isSingleNested && !isUnderneathMap) {
  65. // Only handle nested schemas 1-level deep to avoid infinite
  66. // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
  67. schemaType.schema.eachPath(function(_path, _schemaType) {
  68. if (_path === '_id' && _schemaType.auto) {
  69. // Ignore _id if auto id so we don't create subdocs
  70. return;
  71. }
  72. const def = _schemaType.getDefault(null, true);
  73. if (!isModified(modified, path + '.' + _path) &&
  74. typeof def !== 'undefined') {
  75. castedDoc = castedDoc || {};
  76. castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
  77. castedDoc.$setOnInsert[path + '.' + _path] = def;
  78. updatedValues[path + '.' + _path] = def;
  79. }
  80. });
  81. } else {
  82. const def = schemaType.getDefault(null, true);
  83. if (!isModified(modified, path) && typeof def !== 'undefined') {
  84. castedDoc = castedDoc || {};
  85. castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
  86. castedDoc.$setOnInsert[path] = def;
  87. updatedValues[path] = def;
  88. }
  89. }
  90. });
  91. return castedDoc;
  92. };
  93. function isModified(modified, path) {
  94. if (modified[path]) {
  95. return true;
  96. }
  97. const sp = path.split('.');
  98. let cur = sp[0];
  99. for (let i = 1; i < sp.length; ++i) {
  100. if (modified[cur]) {
  101. return true;
  102. }
  103. cur += '.' + sp[i];
  104. }
  105. return false;
  106. }