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

'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;