You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							269 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							269 lines
						
					
					
						
							11 KiB
						
					
					
				| "use strict";
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.IndexInformationOperation = exports.IndexExistsOperation = exports.ListIndexesOperation = exports.DropIndexesOperation = exports.DropIndexOperation = exports.EnsureIndexOperation = exports.CreateIndexOperation = exports.CreateIndexesOperation = exports.IndexesOperation = void 0;
 | |
| const error_1 = require("../error");
 | |
| const read_preference_1 = require("../read_preference");
 | |
| const utils_1 = require("../utils");
 | |
| const command_1 = require("./command");
 | |
| const common_functions_1 = require("./common_functions");
 | |
| const operation_1 = require("./operation");
 | |
| const VALID_INDEX_OPTIONS = new Set([
 | |
|     'background',
 | |
|     'unique',
 | |
|     'name',
 | |
|     'partialFilterExpression',
 | |
|     'sparse',
 | |
|     'hidden',
 | |
|     'expireAfterSeconds',
 | |
|     'storageEngine',
 | |
|     'collation',
 | |
|     'version',
 | |
|     // text indexes
 | |
|     'weights',
 | |
|     'default_language',
 | |
|     'language_override',
 | |
|     'textIndexVersion',
 | |
|     // 2d-sphere indexes
 | |
|     '2dsphereIndexVersion',
 | |
|     // 2d indexes
 | |
|     'bits',
 | |
|     'min',
 | |
|     'max',
 | |
|     // geoHaystack Indexes
 | |
|     'bucketSize',
 | |
|     // wildcard indexes
 | |
|     'wildcardProjection'
 | |
| ]);
 | |
| function isIndexDirection(x) {
 | |
|     return (typeof x === 'number' || x === '2d' || x === '2dsphere' || x === 'text' || x === 'geoHaystack');
 | |
| }
 | |
| function isSingleIndexTuple(t) {
 | |
|     return Array.isArray(t) && t.length === 2 && isIndexDirection(t[1]);
 | |
| }
 | |
| function makeIndexSpec(indexSpec, options) {
 | |
|     const key = new Map();
 | |
|     const indexSpecs = !Array.isArray(indexSpec) || isSingleIndexTuple(indexSpec) ? [indexSpec] : indexSpec;
 | |
|     // Iterate through array and handle different types
 | |
|     for (const spec of indexSpecs) {
 | |
|         if (typeof spec === 'string') {
 | |
|             key.set(spec, 1);
 | |
|         }
 | |
|         else if (Array.isArray(spec)) {
 | |
|             key.set(spec[0], spec[1] ?? 1);
 | |
|         }
 | |
|         else if (spec instanceof Map) {
 | |
|             for (const [property, value] of spec) {
 | |
|                 key.set(property, value);
 | |
|             }
 | |
|         }
 | |
|         else if ((0, utils_1.isObject)(spec)) {
 | |
|             for (const [property, value] of Object.entries(spec)) {
 | |
|                 key.set(property, value);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return { ...options, key };
 | |
| }
 | |
| /** @internal */
 | |
| class IndexesOperation extends operation_1.AbstractOperation {
 | |
|     constructor(collection, options) {
 | |
|         super(options);
 | |
|         this.options = options;
 | |
|         this.collection = collection;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const coll = this.collection;
 | |
|         const options = this.options;
 | |
|         (0, common_functions_1.indexInformation)(coll.s.db, coll.collectionName, { full: true, ...options, readPreference: this.readPreference, session }, callback);
 | |
|     }
 | |
| }
 | |
| exports.IndexesOperation = IndexesOperation;
 | |
| /** @internal */
 | |
| class CreateIndexesOperation extends command_1.CommandOperation {
 | |
|     constructor(parent, collectionName, indexes, options) {
 | |
|         super(parent, options);
 | |
|         this.options = options ?? {};
 | |
|         this.collectionName = collectionName;
 | |
|         this.indexes = indexes.map(userIndex => {
 | |
|             // Ensure the key is a Map to preserve index key ordering
 | |
|             const key = userIndex.key instanceof Map ? userIndex.key : new Map(Object.entries(userIndex.key));
 | |
|             const name = userIndex.name != null ? userIndex.name : Array.from(key).flat().join('_');
 | |
|             const validIndexOptions = Object.fromEntries(Object.entries({ ...userIndex }).filter(([optionName]) => VALID_INDEX_OPTIONS.has(optionName)));
 | |
|             return {
 | |
|                 ...validIndexOptions,
 | |
|                 name,
 | |
|                 key
 | |
|             };
 | |
|         });
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const options = this.options;
 | |
|         const indexes = this.indexes;
 | |
|         const serverWireVersion = (0, utils_1.maxWireVersion)(server);
 | |
|         const cmd = { createIndexes: this.collectionName, indexes };
 | |
|         if (options.commitQuorum != null) {
 | |
|             if (serverWireVersion < 9) {
 | |
|                 callback(new error_1.MongoCompatibilityError('Option `commitQuorum` for `createIndexes` not supported on servers < 4.4'));
 | |
|                 return;
 | |
|             }
 | |
|             cmd.commitQuorum = options.commitQuorum;
 | |
|         }
 | |
|         // collation is set on each index, it should not be defined at the root
 | |
|         this.options.collation = undefined;
 | |
|         super.executeCommand(server, session, cmd, err => {
 | |
|             if (err) {
 | |
|                 callback(err);
 | |
|                 return;
 | |
|             }
 | |
|             const indexNames = indexes.map(index => index.name || '');
 | |
|             callback(undefined, indexNames);
 | |
|         });
 | |
|     }
 | |
| }
 | |
| exports.CreateIndexesOperation = CreateIndexesOperation;
 | |
| /** @internal */
 | |
| class CreateIndexOperation extends CreateIndexesOperation {
 | |
|     constructor(parent, collectionName, indexSpec, options) {
 | |
|         super(parent, collectionName, [makeIndexSpec(indexSpec, options)], options);
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         super.execute(server, session, (err, indexNames) => {
 | |
|             if (err || !indexNames)
 | |
|                 return callback(err);
 | |
|             return callback(undefined, indexNames[0]);
 | |
|         });
 | |
|     }
 | |
| }
 | |
| exports.CreateIndexOperation = CreateIndexOperation;
 | |
| /** @internal */
 | |
| class EnsureIndexOperation extends CreateIndexOperation {
 | |
|     constructor(db, collectionName, indexSpec, options) {
 | |
|         super(db, collectionName, indexSpec, options);
 | |
|         this.readPreference = read_preference_1.ReadPreference.primary;
 | |
|         this.db = db;
 | |
|         this.collectionName = collectionName;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const indexName = this.indexes[0].name;
 | |
|         const cursor = this.db.collection(this.collectionName).listIndexes({ session });
 | |
|         cursor.toArray().then(indexes => {
 | |
|             indexes = Array.isArray(indexes) ? indexes : [indexes];
 | |
|             if (indexes.some(index => index.name === indexName)) {
 | |
|                 callback(undefined, indexName);
 | |
|                 return;
 | |
|             }
 | |
|             super.execute(server, session, callback);
 | |
|         }, error => {
 | |
|             if (error instanceof error_1.MongoError && error.code === error_1.MONGODB_ERROR_CODES.NamespaceNotFound) {
 | |
|                 // ignore "NamespaceNotFound" errors
 | |
|                 return super.execute(server, session, callback);
 | |
|             }
 | |
|             return callback(error);
 | |
|         });
 | |
|     }
 | |
| }
 | |
| exports.EnsureIndexOperation = EnsureIndexOperation;
 | |
| /** @internal */
 | |
| class DropIndexOperation extends command_1.CommandOperation {
 | |
|     constructor(collection, indexName, options) {
 | |
|         super(collection, options);
 | |
|         this.options = options ?? {};
 | |
|         this.collection = collection;
 | |
|         this.indexName = indexName;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const cmd = { dropIndexes: this.collection.collectionName, index: this.indexName };
 | |
|         super.executeCommand(server, session, cmd, callback);
 | |
|     }
 | |
| }
 | |
| exports.DropIndexOperation = DropIndexOperation;
 | |
| /** @internal */
 | |
| class DropIndexesOperation extends DropIndexOperation {
 | |
|     constructor(collection, options) {
 | |
|         super(collection, '*', options);
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         super.execute(server, session, err => {
 | |
|             if (err)
 | |
|                 return callback(err, false);
 | |
|             callback(undefined, true);
 | |
|         });
 | |
|     }
 | |
| }
 | |
| exports.DropIndexesOperation = DropIndexesOperation;
 | |
| /** @internal */
 | |
| class ListIndexesOperation extends command_1.CommandOperation {
 | |
|     constructor(collection, options) {
 | |
|         super(collection, options);
 | |
|         this.options = options ?? {};
 | |
|         this.collectionNamespace = collection.s.namespace;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const serverWireVersion = (0, utils_1.maxWireVersion)(server);
 | |
|         const cursor = this.options.batchSize ? { batchSize: this.options.batchSize } : {};
 | |
|         const command = { listIndexes: this.collectionNamespace.collection, cursor };
 | |
|         // we check for undefined specifically here to allow falsy values
 | |
|         // eslint-disable-next-line no-restricted-syntax
 | |
|         if (serverWireVersion >= 9 && this.options.comment !== undefined) {
 | |
|             command.comment = this.options.comment;
 | |
|         }
 | |
|         super.executeCommand(server, session, command, callback);
 | |
|     }
 | |
| }
 | |
| exports.ListIndexesOperation = ListIndexesOperation;
 | |
| /** @internal */
 | |
| class IndexExistsOperation extends operation_1.AbstractOperation {
 | |
|     constructor(collection, indexes, options) {
 | |
|         super(options);
 | |
|         this.options = options;
 | |
|         this.collection = collection;
 | |
|         this.indexes = indexes;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const coll = this.collection;
 | |
|         const indexes = this.indexes;
 | |
|         (0, common_functions_1.indexInformation)(coll.s.db, coll.collectionName, { ...this.options, readPreference: this.readPreference, session }, (err, indexInformation) => {
 | |
|             // If we have an error return
 | |
|             if (err != null)
 | |
|                 return callback(err);
 | |
|             // Let's check for the index names
 | |
|             if (!Array.isArray(indexes))
 | |
|                 return callback(undefined, indexInformation[indexes] != null);
 | |
|             // Check in list of indexes
 | |
|             for (let i = 0; i < indexes.length; i++) {
 | |
|                 if (indexInformation[indexes[i]] == null) {
 | |
|                     return callback(undefined, false);
 | |
|                 }
 | |
|             }
 | |
|             // All keys found return true
 | |
|             return callback(undefined, true);
 | |
|         });
 | |
|     }
 | |
| }
 | |
| exports.IndexExistsOperation = IndexExistsOperation;
 | |
| /** @internal */
 | |
| class IndexInformationOperation extends operation_1.AbstractOperation {
 | |
|     constructor(db, name, options) {
 | |
|         super(options);
 | |
|         this.options = options ?? {};
 | |
|         this.db = db;
 | |
|         this.name = name;
 | |
|     }
 | |
|     execute(server, session, callback) {
 | |
|         const db = this.db;
 | |
|         const name = this.name;
 | |
|         (0, common_functions_1.indexInformation)(db, name, { ...this.options, readPreference: this.readPreference, session }, callback);
 | |
|     }
 | |
| }
 | |
| exports.IndexInformationOperation = IndexInformationOperation;
 | |
| (0, operation_1.defineAspects)(ListIndexesOperation, [
 | |
|     operation_1.Aspect.READ_OPERATION,
 | |
|     operation_1.Aspect.RETRYABLE,
 | |
|     operation_1.Aspect.CURSOR_CREATING
 | |
| ]);
 | |
| (0, operation_1.defineAspects)(CreateIndexesOperation, [operation_1.Aspect.WRITE_OPERATION]);
 | |
| (0, operation_1.defineAspects)(CreateIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
 | |
| (0, operation_1.defineAspects)(EnsureIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
 | |
| (0, operation_1.defineAspects)(DropIndexOperation, [operation_1.Aspect.WRITE_OPERATION]);
 | |
| (0, operation_1.defineAspects)(DropIndexesOperation, [operation_1.Aspect.WRITE_OPERATION]);
 | |
| //# sourceMappingURL=indexes.js.map
 |