create_indexes.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. 'use strict';
  2. const Aspect = require('./operation').Aspect;
  3. const defineAspects = require('./operation').defineAspects;
  4. const CommandOperationV2 = require('./command_v2');
  5. const MongoError = require('../core').MongoError;
  6. const parseIndexOptions = require('../utils').parseIndexOptions;
  7. const maxWireVersion = require('../core/utils').maxWireVersion;
  8. const VALID_INDEX_OPTIONS = new Set([
  9. 'background',
  10. 'unique',
  11. 'name',
  12. 'partialFilterExpression',
  13. 'sparse',
  14. 'expireAfterSeconds',
  15. 'storageEngine',
  16. 'collation',
  17. // text indexes
  18. 'weights',
  19. 'default_language',
  20. 'language_override',
  21. 'textIndexVersion',
  22. // 2d-sphere indexes
  23. '2dsphereIndexVersion',
  24. // 2d indexes
  25. 'bits',
  26. 'min',
  27. 'max',
  28. // geoHaystack Indexes
  29. 'bucketSize',
  30. // wildcard indexes
  31. 'wildcardProjection'
  32. ]);
  33. class CreateIndexesOperation extends CommandOperationV2 {
  34. /**
  35. * @ignore
  36. */
  37. constructor(parent, collection, indexes, options) {
  38. super(parent, options);
  39. this.collection = collection;
  40. // createIndex can be called with a variety of styles:
  41. // coll.createIndex('a');
  42. // coll.createIndex({ a: 1 });
  43. // coll.createIndex([['a', 1]]);
  44. // createIndexes is always called with an array of index spec objects
  45. if (!Array.isArray(indexes) || Array.isArray(indexes[0])) {
  46. this.onlyReturnNameOfCreatedIndex = true;
  47. // TODO: remove in v4 (breaking change); make createIndex return full response as createIndexes does
  48. const indexParameters = parseIndexOptions(indexes);
  49. // Generate the index name
  50. const name = typeof options.name === 'string' ? options.name : indexParameters.name;
  51. // Set up the index
  52. const indexSpec = { name, key: indexParameters.fieldHash };
  53. // merge valid index options into the index spec
  54. for (let optionName in options) {
  55. if (VALID_INDEX_OPTIONS.has(optionName)) {
  56. indexSpec[optionName] = options[optionName];
  57. }
  58. }
  59. this.indexes = [indexSpec];
  60. return;
  61. }
  62. this.indexes = indexes;
  63. }
  64. /**
  65. * @ignore
  66. */
  67. execute(server, callback) {
  68. const options = this.options;
  69. const indexes = this.indexes;
  70. const serverWireVersion = maxWireVersion(server);
  71. // Ensure we generate the correct name if the parameter is not set
  72. for (let i = 0; i < indexes.length; i++) {
  73. // Did the user pass in a collation, check if our write server supports it
  74. if (indexes[i].collation && serverWireVersion < 5) {
  75. callback(
  76. new MongoError(
  77. `Server ${server.name}, which reports wire version ${serverWireVersion}, does not support collation`
  78. )
  79. );
  80. return;
  81. }
  82. if (indexes[i].name == null) {
  83. const keys = [];
  84. for (let name in indexes[i].key) {
  85. keys.push(`${name}_${indexes[i].key[name]}`);
  86. }
  87. // Set the name
  88. indexes[i].name = keys.join('_');
  89. }
  90. }
  91. const cmd = { createIndexes: this.collection, indexes };
  92. if (options.commitQuorum != null) {
  93. if (serverWireVersion < 9) {
  94. callback(
  95. new MongoError('`commitQuorum` option for `createIndexes` not supported on servers < 4.4')
  96. );
  97. return;
  98. }
  99. cmd.commitQuorum = options.commitQuorum;
  100. }
  101. // collation is set on each index, it should not be defined at the root
  102. this.options.collation = undefined;
  103. super.executeCommand(server, cmd, (err, result) => {
  104. if (err) {
  105. callback(err);
  106. return;
  107. }
  108. callback(null, this.onlyReturnNameOfCreatedIndex ? indexes[0].name : result);
  109. });
  110. }
  111. }
  112. defineAspects(CreateIndexesOperation, [Aspect.WRITE_OPERATION, Aspect.EXECUTE_WITH_SELECTION]);
  113. module.exports = CreateIndexesOperation;