indexes.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.IndexInformationOperation = exports.IndexExistsOperation = exports.ListIndexesCursor = exports.ListIndexesOperation = exports.DropIndexesOperation = exports.DropIndexOperation = exports.EnsureIndexOperation = exports.CreateIndexOperation = exports.CreateIndexesOperation = exports.IndexesOperation = void 0;
  4. const abstract_cursor_1 = require("../cursor/abstract_cursor");
  5. const error_1 = require("../error");
  6. const read_preference_1 = require("../read_preference");
  7. const utils_1 = require("../utils");
  8. const command_1 = require("./command");
  9. const common_functions_1 = require("./common_functions");
  10. const execute_operation_1 = require("./execute_operation");
  11. const operation_1 = require("./operation");
  12. const LIST_INDEXES_WIRE_VERSION = 3;
  13. const VALID_INDEX_OPTIONS = new Set([
  14. 'background',
  15. 'unique',
  16. 'name',
  17. 'partialFilterExpression',
  18. 'sparse',
  19. 'hidden',
  20. 'expireAfterSeconds',
  21. 'storageEngine',
  22. 'collation',
  23. 'version',
  24. // text indexes
  25. 'weights',
  26. 'default_language',
  27. 'language_override',
  28. 'textIndexVersion',
  29. // 2d-sphere indexes
  30. '2dsphereIndexVersion',
  31. // 2d indexes
  32. 'bits',
  33. 'min',
  34. 'max',
  35. // geoHaystack Indexes
  36. 'bucketSize',
  37. // wildcard indexes
  38. 'wildcardProjection'
  39. ]);
  40. function makeIndexSpec(indexSpec, options) {
  41. const indexParameters = (0, utils_1.parseIndexOptions)(indexSpec);
  42. // Generate the index name
  43. const name = typeof options.name === 'string' ? options.name : indexParameters.name;
  44. // Set up the index
  45. const finalIndexSpec = { name, key: indexParameters.fieldHash };
  46. // merge valid index options into the index spec
  47. for (const optionName in options) {
  48. if (VALID_INDEX_OPTIONS.has(optionName)) {
  49. finalIndexSpec[optionName] = options[optionName];
  50. }
  51. }
  52. return finalIndexSpec;
  53. }
  54. /** @internal */
  55. class IndexesOperation extends operation_1.AbstractOperation {
  56. constructor(collection, options) {
  57. super(options);
  58. this.options = options;
  59. this.collection = collection;
  60. }
  61. execute(server, session, callback) {
  62. const coll = this.collection;
  63. const options = this.options;
  64. (0, common_functions_1.indexInformation)(coll.s.db, coll.collectionName, { full: true, ...options, readPreference: this.readPreference, session }, callback);
  65. }
  66. }
  67. exports.IndexesOperation = IndexesOperation;
  68. /** @internal */
  69. class CreateIndexesOperation extends command_1.CommandOperation {
  70. constructor(parent, collectionName, indexes, options) {
  71. super(parent, options);
  72. this.options = options !== null && options !== void 0 ? options : {};
  73. this.collectionName = collectionName;
  74. this.indexes = indexes;
  75. }
  76. execute(server, session, callback) {
  77. const options = this.options;
  78. const indexes = this.indexes;
  79. const serverWireVersion = (0, utils_1.maxWireVersion)(server);
  80. // Ensure we generate the correct name if the parameter is not set
  81. for (let i = 0; i < indexes.length; i++) {
  82. // Did the user pass in a collation, check if our write server supports it
  83. if (indexes[i].collation && serverWireVersion < 5) {
  84. callback(new error_1.MongoCompatibilityError(`Server ${server.name}, which reports wire version ${serverWireVersion}, ` +
  85. 'does not support collation'));
  86. return;
  87. }
  88. if (indexes[i].name == null) {
  89. const keys = [];
  90. for (const name in indexes[i].key) {
  91. keys.push(`${name}_${indexes[i].key[name]}`);
  92. }
  93. // Set the name
  94. indexes[i].name = keys.join('_');
  95. }
  96. }
  97. const cmd = { createIndexes: this.collectionName, indexes };
  98. if (options.commitQuorum != null) {
  99. if (serverWireVersion < 9) {
  100. callback(new error_1.MongoCompatibilityError('Option `commitQuorum` for `createIndexes` not supported on servers < 4.4'));
  101. return;
  102. }
  103. cmd.commitQuorum = options.commitQuorum;
  104. }
  105. // collation is set on each index, it should not be defined at the root
  106. this.options.collation = undefined;
  107. super.executeCommand(server, session, cmd, err => {
  108. if (err) {
  109. callback(err);
  110. return;
  111. }
  112. const indexNames = indexes.map(index => index.name || '');
  113. callback(undefined, indexNames);
  114. });
  115. }
  116. }
  117. exports.CreateIndexesOperation = CreateIndexesOperation;
  118. /** @internal */
  119. class CreateIndexOperation extends CreateIndexesOperation {
  120. constructor(parent, collectionName, indexSpec, options) {
  121. // createIndex can be called with a variety of styles:
  122. // coll.createIndex('a');
  123. // coll.createIndex({ a: 1 });
  124. // coll.createIndex([['a', 1]]);
  125. // createIndexes is always called with an array of index spec objects
  126. super(parent, collectionName, [makeIndexSpec(indexSpec, options)], options);
  127. }
  128. execute(server, session, callback) {
  129. super.execute(server, session, (err, indexNames) => {
  130. if (err || !indexNames)
  131. return callback(err);
  132. return callback(undefined, indexNames[0]);
  133. });
  134. }
  135. }
  136. exports.CreateIndexOperation = CreateIndexOperation;
  137. /** @internal */
  138. class EnsureIndexOperation extends CreateIndexOperation {
  139. constructor(db, collectionName, indexSpec, options) {
  140. super(db, collectionName, indexSpec, options);
  141. this.readPreference = read_preference_1.ReadPreference.primary;
  142. this.db = db;
  143. this.collectionName = collectionName;
  144. }
  145. execute(server, session, callback) {
  146. const indexName = this.indexes[0].name;
  147. const cursor = this.db.collection(this.collectionName).listIndexes({ session });
  148. cursor.toArray((err, indexes) => {
  149. /// ignore "NamespaceNotFound" errors
  150. if (err && err.code !== error_1.MONGODB_ERROR_CODES.NamespaceNotFound) {
  151. return callback(err);
  152. }
  153. if (indexes) {
  154. indexes = Array.isArray(indexes) ? indexes : [indexes];
  155. if (indexes.some(index => index.name === indexName)) {
  156. callback(undefined, indexName);
  157. return;
  158. }
  159. }
  160. super.execute(server, session, callback);
  161. });
  162. }
  163. }
  164. exports.EnsureIndexOperation = EnsureIndexOperation;
  165. /** @internal */
  166. class DropIndexOperation extends command_1.CommandOperation {
  167. constructor(collection, indexName, options) {
  168. super(collection, options);
  169. this.options = options !== null && options !== void 0 ? options : {};
  170. this.collection = collection;
  171. this.indexName = indexName;
  172. }
  173. execute(server, session, callback) {
  174. const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName };
  175. super.executeCommand(server, session, cmd, callback);
  176. }
  177. }
  178. exports.DropIndexOperation = DropIndexOperation;
  179. /** @internal */
  180. class DropIndexesOperation extends DropIndexOperation {
  181. constructor(collection, options) {
  182. super(collection, '*', options);
  183. }
  184. execute(server, session, callback) {
  185. super.execute(server, session, err => {
  186. if (err)
  187. return callback(err, false);
  188. callback(undefined, true);
  189. });
  190. }
  191. }
  192. exports.DropIndexesOperation = DropIndexesOperation;
  193. /** @internal */
  194. class ListIndexesOperation extends command_1.CommandOperation {
  195. constructor(collection, options) {
  196. super(collection, options);
  197. this.options = options !== null && options !== void 0 ? options : {};
  198. this.collectionNamespace = collection.s.namespace;
  199. }
  200. execute(server, session, callback) {
  201. const serverWireVersion = (0, utils_1.maxWireVersion)(server);
  202. if (serverWireVersion < LIST_INDEXES_WIRE_VERSION) {
  203. const systemIndexesNS = this.collectionNamespace.withCollection('system.indexes');
  204. const collectionNS = this.collectionNamespace.toString();
  205. server.query(systemIndexesNS, { query: { ns: collectionNS } }, { ...this.options, readPreference: this.readPreference }, callback);
  206. return;
  207. }
  208. const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
  209. super.executeCommand(server, session, { listIndexes: this.collectionNamespace.collection, cursor }, callback);
  210. }
  211. }
  212. exports.ListIndexesOperation = ListIndexesOperation;
  213. /** @public */
  214. class ListIndexesCursor extends abstract_cursor_1.AbstractCursor {
  215. constructor(collection, options) {
  216. super((0, utils_1.getTopology)(collection), collection.s.namespace, options);
  217. this.parent = collection;
  218. this.options = options;
  219. }
  220. clone() {
  221. return new ListIndexesCursor(this.parent, {
  222. ...this.options,
  223. ...this.cursorOptions
  224. });
  225. }
  226. /** @internal */
  227. _initialize(session, callback) {
  228. const operation = new ListIndexesOperation(this.parent, {
  229. ...this.cursorOptions,
  230. ...this.options,
  231. session
  232. });
  233. (0, execute_operation_1.executeOperation)((0, utils_1.getTopology)(this.parent), operation, (err, response) => {
  234. if (err || response == null)
  235. return callback(err);
  236. // TODO: NODE-2882
  237. callback(undefined, { server: operation.server, session, response });
  238. });
  239. }
  240. }
  241. exports.ListIndexesCursor = ListIndexesCursor;
  242. /** @internal */
  243. class IndexExistsOperation extends operation_1.AbstractOperation {
  244. constructor(collection, indexes, options) {
  245. super(options);
  246. this.options = options;
  247. this.collection = collection;
  248. this.indexes = indexes;
  249. }
  250. execute(server, session, callback) {
  251. const coll = this.collection;
  252. const indexes = this.indexes;
  253. (0, common_functions_1.indexInformation)(coll.s.db, coll.collectionName, { ...this.options, readPreference: this.readPreference, session }, (err, indexInformation) => {
  254. // If we have an error return
  255. if (err != null)
  256. return callback(err);
  257. // Let's check for the index names
  258. if (!Array.isArray(indexes))
  259. return callback(undefined, indexInformation[indexes] != null);
  260. // Check in list of indexes
  261. for (let i = 0; i < indexes.length; i++) {
  262. if (indexInformation[indexes[i]] == null) {
  263. return callback(undefined, false);
  264. }
  265. }
  266. // All keys found return true
  267. return callback(undefined, true);
  268. });
  269. }
  270. }
  271. exports.IndexExistsOperation = IndexExistsOperation;
  272. /** @internal */
  273. class IndexInformationOperation extends operation_1.AbstractOperation {
  274. constructor(db, name, options) {
  275. super(options);
  276. this.options = options !== null && options !== void 0 ? options : {};
  277. this.db = db;
  278. this.name = name;
  279. }
  280. execute(server, session, callback) {
  281. const db = this.db;
  282. const name = this.name;
  283. (0, common_functions_1.indexInformation)(db, name, { ...this.options, readPreference: this.readPreference, session }, callback);
  284. }
  285. }
  286. exports.IndexInformationOperation = IndexInformationOperation;
  287. (0, operation_1.defineAspects)(ListIndexesOperation, [
  288. operation_1.Aspect.READ_OPERATION,
  289. operation_1.Aspect.RETRYABLE,
  290. operation_1.Aspect.CURSOR_CREATING
  291. ]);
  292. (0, operation_1.defineAspects)(CreateIndexesOperation, [operation_1.Aspect.WRITE_OPERATION]);
  293. (0, operation_1.defineAspects)(CreateIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
  294. (0, operation_1.defineAspects)(EnsureIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
  295. (0, operation_1.defineAspects)(DropIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
  296. (0, operation_1.defineAspects)(DropIndexesOperation, [operation_1.Aspect.WRITE_OPERATION]);
  297. //# sourceMappingURL=indexes.js.map