getEmbeddedDiscriminatorPath.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 'use strict';
  2. const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
  3. const get = require('../get');
  4. const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
  5. const updatedPathsByArrayFilter = require('../update/updatedPathsByArrayFilter');
  6. /*!
  7. * Like `schema.path()`, except with a document, because impossible to
  8. * determine path type without knowing the embedded discriminator key.
  9. */
  10. module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path, options) {
  11. const parts = path.split('.');
  12. let schematype = null;
  13. let type = 'adhocOrUndefined';
  14. filter = filter || {};
  15. update = update || {};
  16. const arrayFilters = options != null && Array.isArray(options.arrayFilters) ?
  17. options.arrayFilters : [];
  18. const updatedPathsByFilter = updatedPathsByArrayFilter(update);
  19. for (let i = 0; i < parts.length; ++i) {
  20. const subpath = cleanPositionalOperators(parts.slice(0, i + 1).join('.'));
  21. schematype = schema.path(subpath);
  22. if (schematype == null) {
  23. continue;
  24. }
  25. type = schema.pathType(subpath);
  26. if ((schematype.$isSingleNested || schematype.$isMongooseDocumentArrayElement) &&
  27. schematype.schema.discriminators != null) {
  28. const key = get(schematype, 'schema.options.discriminatorKey');
  29. const discriminatorValuePath = subpath + '.' + key;
  30. const discriminatorFilterPath =
  31. discriminatorValuePath.replace(/\.\d+\./, '.');
  32. let discriminatorKey = null;
  33. if (discriminatorValuePath in filter) {
  34. discriminatorKey = filter[discriminatorValuePath];
  35. }
  36. if (discriminatorFilterPath in filter) {
  37. discriminatorKey = filter[discriminatorFilterPath];
  38. }
  39. const wrapperPath = subpath.replace(/\.\d+$/, '');
  40. if (schematype.$isMongooseDocumentArrayElement &&
  41. get(filter[wrapperPath], '$elemMatch.' + key) != null) {
  42. discriminatorKey = filter[wrapperPath].$elemMatch[key];
  43. }
  44. if (discriminatorValuePath in update) {
  45. discriminatorKey = update[discriminatorValuePath];
  46. }
  47. for (const filterKey of Object.keys(updatedPathsByFilter)) {
  48. const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
  49. const arrayFilterKey = filterKey + '.' + key;
  50. if (schemaKey === discriminatorFilterPath) {
  51. const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey));
  52. if (filter != null) {
  53. discriminatorKey = filter[arrayFilterKey];
  54. }
  55. }
  56. }
  57. if (discriminatorKey == null) {
  58. continue;
  59. }
  60. const discriminatorSchema = getDiscriminatorByValue(schematype.caster.discriminators, discriminatorKey).schema;
  61. const rest = parts.slice(i + 1).join('.');
  62. schematype = discriminatorSchema.path(rest);
  63. if (schematype != null) {
  64. type = discriminatorSchema._getPathType(rest);
  65. break;
  66. }
  67. }
  68. }
  69. return { type: type, schematype: schematype };
  70. };