getIndexes.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. 'use strict';
  2. const get = require('../get');
  3. const utils = require('../../utils');
  4. /*!
  5. * Gather all indexes defined in the schema, including single nested,
  6. * document arrays, and embedded discriminators.
  7. */
  8. module.exports = function getIndexes(schema) {
  9. let indexes = [];
  10. const schemaStack = new WeakMap();
  11. const indexTypes = schema.constructor.indexTypes;
  12. const collectIndexes = function(schema, prefix) {
  13. // Ignore infinitely nested schemas, if we've already seen this schema
  14. // along this path there must be a cycle
  15. if (schemaStack.has(schema)) {
  16. return;
  17. }
  18. schemaStack.set(schema, true);
  19. prefix = prefix || '';
  20. const keys = Object.keys(schema.paths);
  21. const length = keys.length;
  22. for (let i = 0; i < length; ++i) {
  23. const key = keys[i];
  24. const path = schema.paths[key];
  25. if (path.$isMongooseDocumentArray || path.$isSingleNested) {
  26. if (get(path, 'options.excludeIndexes') !== true &&
  27. get(path, 'schemaOptions.excludeIndexes') !== true) {
  28. collectIndexes(path.schema, prefix + key + '.');
  29. }
  30. if (path.schema.discriminators != null) {
  31. const discriminators = path.schema.discriminators;
  32. const discriminatorKeys = Object.keys(discriminators);
  33. for (const discriminatorKey of discriminatorKeys) {
  34. collectIndexes(discriminators[discriminatorKey]._originalSchema,
  35. prefix + key + '.');
  36. }
  37. }
  38. // Retained to minimize risk of backwards breaking changes due to
  39. // gh-6113
  40. if (path.$isMongooseDocumentArray) {
  41. continue;
  42. }
  43. }
  44. const index = path._index || (path.caster && path.caster._index);
  45. if (index !== false && index !== null && index !== undefined) {
  46. const field = {};
  47. const isObject = utils.isObject(index);
  48. const options = isObject ? index : {};
  49. const type = typeof index === 'string' ? index :
  50. isObject ? index.type :
  51. false;
  52. if (type && indexTypes.indexOf(type) !== -1) {
  53. field[prefix + key] = type;
  54. } else if (options.text) {
  55. field[prefix + key] = 'text';
  56. delete options.text;
  57. } else {
  58. field[prefix + key] = 1;
  59. }
  60. delete options.type;
  61. if (!('background' in options)) {
  62. options.background = true;
  63. }
  64. indexes.push([field, options]);
  65. }
  66. }
  67. schemaStack.delete(schema);
  68. if (prefix) {
  69. fixSubIndexPaths(schema, prefix);
  70. } else {
  71. schema._indexes.forEach(function(index) {
  72. if (!('background' in index[1])) {
  73. index[1].background = true;
  74. }
  75. });
  76. indexes = indexes.concat(schema._indexes);
  77. }
  78. };
  79. collectIndexes(schema);
  80. return indexes;
  81. /*!
  82. * Checks for indexes added to subdocs using Schema.index().
  83. * These indexes need their paths prefixed properly.
  84. *
  85. * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
  86. */
  87. function fixSubIndexPaths(schema, prefix) {
  88. const subindexes = schema._indexes;
  89. const len = subindexes.length;
  90. for (let i = 0; i < len; ++i) {
  91. const indexObj = subindexes[i][0];
  92. const keys = Object.keys(indexObj);
  93. const klen = keys.length;
  94. const newindex = {};
  95. // use forward iteration, order matters
  96. for (let j = 0; j < klen; ++j) {
  97. const key = keys[j];
  98. newindex[prefix + key] = indexObj[key];
  99. }
  100. indexes.push([newindex, subindexes[i][1]]);
  101. }
  102. }
  103. };