isIndexEqual.js 2.7 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} key 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(key, 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. // background: true,
  22. // weights: { name: 1 },
  23. // default_language: 'english',
  24. // language_override: 'language',
  25. // textIndexVersion: 3
  26. // }
  27. if (dbIndex.textIndexVersion != null) {
  28. const weights = dbIndex.weights;
  29. if (Object.keys(weights).length !== Object.keys(key).length) {
  30. return false;
  31. }
  32. for (const prop of Object.keys(weights)) {
  33. if (!(prop in key)) {
  34. return false;
  35. }
  36. const weight = weights[prop];
  37. if (weight !== get(options, 'weights.' + prop) && !(weight === 1 && get(options, 'weights.' + prop) == null)) {
  38. return false;
  39. }
  40. }
  41. if (options['default_language'] !== dbIndex['default_language']) {
  42. return dbIndex['default_language'] === 'english' && options['default_language'] == null;
  43. }
  44. return true;
  45. }
  46. const optionKeys = [
  47. 'unique',
  48. 'partialFilterExpression',
  49. 'sparse',
  50. 'expireAfterSeconds',
  51. 'collation'
  52. ];
  53. for (const key of optionKeys) {
  54. if (!(key in options) && !(key in dbIndex)) {
  55. continue;
  56. }
  57. if (key === 'collation') {
  58. if (options[key] == null || dbIndex[key] == null) {
  59. return options[key] == null && dbIndex[key] == null;
  60. }
  61. const definedKeys = Object.keys(options.collation);
  62. const schemaCollation = options.collation;
  63. const dbCollation = dbIndex.collation;
  64. for (const opt of definedKeys) {
  65. if (get(schemaCollation, opt) !== get(dbCollation, opt)) {
  66. return false;
  67. }
  68. }
  69. } else if (!utils.deepEqual(options[key], dbIndex[key])) {
  70. return false;
  71. }
  72. }
  73. const schemaIndexKeys = Object.keys(key);
  74. const dbIndexKeys = Object.keys(dbIndex.key);
  75. if (schemaIndexKeys.length !== dbIndexKeys.length) {
  76. return false;
  77. }
  78. for (let i = 0; i < schemaIndexKeys.length; ++i) {
  79. if (schemaIndexKeys[i] !== dbIndexKeys[i]) {
  80. return false;
  81. }
  82. if (!utils.deepEqual(key[schemaIndexKeys[i]], dbIndex.key[dbIndexKeys[i]])) {
  83. return false;
  84. }
  85. }
  86. return true;
  87. };