applyProjection.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. 'use strict';
  2. const hasIncludedChildren = require('./hasIncludedChildren');
  3. const isExclusive = require('./isExclusive');
  4. const isInclusive = require('./isInclusive');
  5. const isPOJO = require('../../utils').isPOJO;
  6. module.exports = function applyProjection(doc, projection, _hasIncludedChildren) {
  7. if (projection == null) {
  8. return doc;
  9. }
  10. if (doc == null) {
  11. return doc;
  12. }
  13. let exclude = null;
  14. if (isInclusive(projection)) {
  15. exclude = false;
  16. } else if (isExclusive(projection)) {
  17. exclude = true;
  18. }
  19. if (exclude == null) {
  20. return doc;
  21. } else if (exclude) {
  22. _hasIncludedChildren = _hasIncludedChildren || hasIncludedChildren(projection);
  23. return applyExclusiveProjection(doc, projection, _hasIncludedChildren);
  24. } else {
  25. _hasIncludedChildren = _hasIncludedChildren || hasIncludedChildren(projection);
  26. return applyInclusiveProjection(doc, projection, _hasIncludedChildren);
  27. }
  28. };
  29. function applyExclusiveProjection(doc, projection, hasIncludedChildren, projectionLimb, prefix) {
  30. if (doc == null || typeof doc !== 'object') {
  31. return doc;
  32. }
  33. const ret = { ...doc };
  34. projectionLimb = prefix ? (projectionLimb || {}) : projection;
  35. for (const key of Object.keys(ret)) {
  36. const fullPath = prefix ? prefix + '.' + key : key;
  37. if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) {
  38. if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
  39. ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  40. } else {
  41. delete ret[key];
  42. }
  43. } else if (hasIncludedChildren[fullPath]) {
  44. ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  45. }
  46. }
  47. return ret;
  48. }
  49. function applyInclusiveProjection(doc, projection, hasIncludedChildren, projectionLimb, prefix) {
  50. if (doc == null || typeof doc !== 'object') {
  51. return doc;
  52. }
  53. const ret = { ...doc };
  54. projectionLimb = prefix ? (projectionLimb || {}) : projection;
  55. for (const key of Object.keys(ret)) {
  56. const fullPath = prefix ? prefix + '.' + key : key;
  57. if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) {
  58. if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) {
  59. ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  60. }
  61. continue;
  62. } else if (hasIncludedChildren[fullPath]) {
  63. ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath);
  64. } else {
  65. delete ret[key];
  66. }
  67. }
  68. return ret;
  69. }