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.
		
		
		
		
		
			
		
			
				
					138 lines
				
				3.7 KiB
			
		
		
			
		
	
	
					138 lines
				
				3.7 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | 
 | ||
|  | const Aspect = require('./operation').Aspect; | ||
|  | const defineAspects = require('./operation').defineAspects; | ||
|  | const CommandOperationV2 = require('./command_v2'); | ||
|  | const MongoError = require('../core').MongoError; | ||
|  | const parseIndexOptions = require('../utils').parseIndexOptions; | ||
|  | const maxWireVersion = require('../core/utils').maxWireVersion; | ||
|  | 
 | ||
|  | const VALID_INDEX_OPTIONS = new Set([ | ||
|  |   'background', | ||
|  |   'unique', | ||
|  |   'name', | ||
|  |   'partialFilterExpression', | ||
|  |   'sparse', | ||
|  |   'expireAfterSeconds', | ||
|  |   'storageEngine', | ||
|  |   'collation', | ||
|  | 
 | ||
|  |   // text indexes
 | ||
|  |   'weights', | ||
|  |   'default_language', | ||
|  |   'language_override', | ||
|  |   'textIndexVersion', | ||
|  | 
 | ||
|  |   // 2d-sphere indexes
 | ||
|  |   '2dsphereIndexVersion', | ||
|  | 
 | ||
|  |   // 2d indexes
 | ||
|  |   'bits', | ||
|  |   'min', | ||
|  |   'max', | ||
|  | 
 | ||
|  |   // geoHaystack Indexes
 | ||
|  |   'bucketSize', | ||
|  | 
 | ||
|  |   // wildcard indexes
 | ||
|  |   'wildcardProjection' | ||
|  | ]); | ||
|  | 
 | ||
|  | class CreateIndexesOperation extends CommandOperationV2 { | ||
|  |   /** | ||
|  |    * @ignore | ||
|  |    */ | ||
|  |   constructor(parent, collection, indexes, options) { | ||
|  |     super(parent, options); | ||
|  |     this.collection = collection; | ||
|  | 
 | ||
|  |     // createIndex can be called with a variety of styles:
 | ||
|  |     //   coll.createIndex('a');
 | ||
|  |     //   coll.createIndex({ a: 1 });
 | ||
|  |     //   coll.createIndex([['a', 1]]);
 | ||
|  |     // createIndexes is always called with an array of index spec objects
 | ||
|  |     if (!Array.isArray(indexes) || Array.isArray(indexes[0])) { | ||
|  |       this.onlyReturnNameOfCreatedIndex = true; | ||
|  |       // TODO: remove in v4 (breaking change); make createIndex return full response as createIndexes does
 | ||
|  | 
 | ||
|  |       const indexParameters = parseIndexOptions(indexes); | ||
|  |       // Generate the index name
 | ||
|  |       const name = typeof options.name === 'string' ? options.name : indexParameters.name; | ||
|  |       // Set up the index
 | ||
|  |       const indexSpec = { name, key: indexParameters.fieldHash }; | ||
|  |       // merge valid index options into the index spec
 | ||
|  |       for (let optionName in options) { | ||
|  |         if (VALID_INDEX_OPTIONS.has(optionName)) { | ||
|  |           indexSpec[optionName] = options[optionName]; | ||
|  |         } | ||
|  |       } | ||
|  |       this.indexes = [indexSpec]; | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     this.indexes = indexes; | ||
|  |   } | ||
|  | 
 | ||
|  |   /** | ||
|  |    * @ignore | ||
|  |    */ | ||
|  |   execute(server, callback) { | ||
|  |     const options = this.options; | ||
|  |     const indexes = this.indexes; | ||
|  | 
 | ||
|  |     const serverWireVersion = maxWireVersion(server); | ||
|  | 
 | ||
|  |     // Ensure we generate the correct name if the parameter is not set
 | ||
|  |     for (let i = 0; i < indexes.length; i++) { | ||
|  |       // Did the user pass in a collation, check if our write server supports it
 | ||
|  |       if (indexes[i].collation && serverWireVersion < 5) { | ||
|  |         callback( | ||
|  |           new MongoError( | ||
|  |             `Server ${server.name}, which reports wire version ${serverWireVersion}, does not support collation` | ||
|  |           ) | ||
|  |         ); | ||
|  |         return; | ||
|  |       } | ||
|  | 
 | ||
|  |       if (indexes[i].name == null) { | ||
|  |         const keys = []; | ||
|  | 
 | ||
|  |         for (let name in indexes[i].key) { | ||
|  |           keys.push(`${name}_${indexes[i].key[name]}`); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Set the name
 | ||
|  |         indexes[i].name = keys.join('_'); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     const cmd = { createIndexes: this.collection, indexes }; | ||
|  | 
 | ||
|  |     if (options.commitQuorum != null) { | ||
|  |       if (serverWireVersion < 9) { | ||
|  |         callback( | ||
|  |           new MongoError('`commitQuorum` option 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, cmd, (err, result) => { | ||
|  |       if (err) { | ||
|  |         callback(err); | ||
|  |         return; | ||
|  |       } | ||
|  | 
 | ||
|  |       callback(null, this.onlyReturnNameOfCreatedIndex ? indexes[0].name : result); | ||
|  |     }); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | defineAspects(CreateIndexesOperation, [Aspect.WRITE_OPERATION, Aspect.EXECUTE_WITH_SELECTION]); | ||
|  | 
 | ||
|  | module.exports = CreateIndexesOperation; |