isIndexEqual.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. 'use strict';
  2. const get = require('../get');
  3. const utils = require('../../utils');
  4. /**
  5. * Given a Mongoose index definition (key + options objects) and a MongoDB server
  6. * index definition, determine if the two indexes are equal.
  7. *
  8. * @param {Object} schemaIndexKeysObject the Mongoose index spec
  9. * @param {Object} options the Mongoose index definition's options
  10. * @param {Object} dbIndex the index in MongoDB as returned by `listIndexes()`
  11. * @api private
  12. */
  13. module.exports = function isIndexEqual(schemaIndexKeysObject, options, dbIndex) {
  14. // Special case: text indexes have a special format in the db. For example,
  15. // `{ name: 'text' }` becomes:
  16. // {
  17. // v: 2,
  18. // key: { _fts: 'text', _ftsx: 1 },
  19. // name: 'name_text',
  20. // ns: 'test.tests',
  21. // weights: { name: 1 },
  22. // default_language: 'english',
  23. // language_override: 'language',
  24. // textIndexVersion: 3
  25. // }
  26. if (dbIndex.textIndexVersion != null) {
  27. delete dbIndex.key._fts;
  28. delete dbIndex.key._ftsx;
  29. const weights = { ...dbIndex.weights, ...dbIndex.key };
  30. if (Object.keys(weights).length !== Object.keys(schemaIndexKeysObject).length) {
  31. return false;
  32. }
  33. for (const prop of Object.keys(weights)) {
  34. if (!(prop in schemaIndexKeysObject)) {
  35. return false;
  36. }
  37. const weight = weights[prop];
  38. if (weight !== get(options, 'weights.' + prop) && !(weight === 1 && get(options, 'weights.' + prop) == null)) {
  39. return false;
  40. }
  41. }
  42. if (options['default_language'] !== dbIndex['default_language']) {
  43. return dbIndex['default_language'] === 'english' && options['default_language'] == null;
  44. }
  45. return true;
  46. }
  47. const optionKeys = [
  48. 'unique',
  49. 'partialFilterExpression',
  50. 'sparse',
  51. 'expireAfterSeconds',
  52. 'collation'
  53. ];
  54. for (const key of optionKeys) {
  55. if (!(key in options) && !(key in dbIndex)) {
  56. continue;
  57. }
  58. if (key === 'collation') {
  59. if (options[key] == null || dbIndex[key] == null) {
  60. return options[key] == null && dbIndex[key] == null;
  61. }
  62. const definedKeys = Object.keys(options.collation);
  63. const schemaCollation = options.collation;
  64. const dbCollation = dbIndex.collation;
  65. for (const opt of definedKeys) {
  66. if (get(schemaCollation, opt) !== get(dbCollation, opt)) {
  67. return false;
  68. }
  69. }
  70. } else if (!utils.deepEqual(options[key], dbIndex[key])) {
  71. return false;
  72. }
  73. }
  74. const schemaIndexKeys = Object.keys(schemaIndexKeysObject);
  75. const dbIndexKeys = Object.keys(dbIndex.key);
  76. if (schemaIndexKeys.length !== dbIndexKeys.length) {
  77. return false;
  78. }
  79. for (let i = 0; i < schemaIndexKeys.length; ++i) {
  80. if (schemaIndexKeys[i] !== dbIndexKeys[i]) {
  81. return false;
  82. }
  83. if (!utils.deepEqual(schemaIndexKeysObject[schemaIndexKeys[i]], dbIndex.key[dbIndexKeys[i]])) {
  84. return false;
  85. }
  86. }
  87. return true;
  88. };