Skip to content

Instantly share code, notes, and snippets.

@backslash112
Forked from ytkang/mongodbIndexExporter.js
Last active August 24, 2021 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save backslash112/842b57b0e086eb4e42f438570ef0f5cf to your computer and use it in GitHub Desktop.
Save backslash112/842b57b0e086eb4e42f438570ef0f5cf to your computer and use it in GitHub Desktop.
Mongodb Index exporter importer

MongoDB Index Exporter and Importer

  • Scripts for exporting and importing MongoDB indexes
  • Just execute export/import script with mongo shell command without install!

Prerequisite

  • MongoShell(mongo command) shoule be required

How to

1. Export mongodb indexes (create index.js)

mongo dbname --quiet mongodbIndexExporter.js > index.js

2. Import index.js to your db

index.js is required

There are 2 modes executing mongodbIndexImporter.js

  • TEST MODE (This will not change anything. Just see the result preview)
mongo dbname --quiet --eval "let mode='DRYRUN';" mongodbIndexImporter.js

DRYRUN mode

  • LIVE MODE (This will change db index)
mongo dbname --quiet --eval "let mode='LIVE';" mongodbIndexImporter.js

LIVE mode

/*
How to export
* mongo is mongoshell command
mongo dbname --quiet mongodbIndexExporter.js > index.js
*/
let collectionNames = db.getCollectionNames();
let index_data = {'collections': []};
for (let i in collectionNames) {
let collection = collectionNames[i];
// let indexes = db[collection].getIndexes();
let indexes;
try {
indexes = db[collection].getIndexes();
} catch (err) { continue; }
let json = { 'name': collection, 'indexes': [] };
for (let j in indexes) {
let idx = indexes[j];
let doc = { 'name': idx['name'], 'key': idx['key'] };
if ('expireAfterSeconds' in idx) {
doc['expireAfterSeconds'] = idx['expireAfterSeconds'];
}
if ('background' in idx) {
doc['background'] = idx['background'];
}
if ('unique' in idx) {
doc['unique'] = idx['unique'];
}
if('collation' in idx) {
doc['collation'] = {
'locale': idx['collation']['locale'],
'strength': idx['collation']['strength'],
};
}
json['indexes'].push(doc)
}
index_data['collections'].push(json);
};
print('let indexes = ');
printjson(index_data);
print(';');
/*
How to (required index.js exported from exporter.js)
* mongo is mongoshell command
mongo dbname --quiet --eval "let mode='DRYRUN';" mongodbIndexImporter.js
*/
// available modes
let LIVE = 'LIVE';
let DRYRUN = 'DRYRUN'; // actually all other words except 'LIVE' are DRYRUN mode.
load('index.js');
if(typeof mode == 'undefined') {
print(red('mode variable required!')+' '+cyan('--eval "let mode=\'DRYRUN\';" or "let mode=\'LIVE\';'));
}
else {
print('*** Index importer: started with ' + yellow(mode) + ' mode ***');
let collections = indexes['collections'];
let collectionNames = db.getCollectionNames();
for (let i in collections) {
let collection = collections[i];
let indexItems = collection["indexes"];
let collectionName = collection['name'];
print('='.repeat(55));
if (collectionNames.indexOf(collectionName) >=0) {
print('collection '+ green(collectionName) + ' already '+green('exists'));
} else {
print('will '+yellow('create')+' collection '+ green(collectionName));
if (mode == LIVE) {
// do create collection
db.createCollection(collectionName)
}
}
let dbCollection = db.getCollection(collectionName);
let existingIndexes = dbCollection.getIndexes();
for(let itemIdx in indexItems) {
let indexItem = indexItems[itemIdx];
let indexName = indexItem['name'];
let indexKey = indexItem['key'];
let checked = false;
for(let eIdx in existingIndexes) {
let existingIndex = existingIndexes[eIdx];
if (existingIndex['name'] == indexName) {
if(!isSameKey(existingIndex, indexItem)) {
print('collection '+green(collectionName)+' index '+green(indexName)+' will be '+red('dropped'));
print('collection '+green(collectionName)+' index '+green(indexName)+' will be '+yellow('re-created'));
if(mode == LIVE) {
dbCollection.dropIndex(indexName);
createIndex(dbCollection, indexName, indexItem);
}
}
else {
print('collection '+green(collectionName)+' index '+green(indexName)+' is same, skip.');
}
checked = true;
break
}
}
if (!checked) {
print('collection '+green(collectionName)+' index '+green(indexName)+' will be '+yellow('created'));
if(mode == LIVE) {
createIndex(dbCollection, indexName, indexItem);
}
}
}
for(let eIdx in existingIndexes) {
let checked = false;
let existingIndex = existingIndexes[eIdx];
for(let itemIdx in indexItems) {
let indexItem = indexItems[itemIdx];
let indexName = indexItem['name'];
if (existingIndex['name'] == indexName) {
checked = true
break
}
}
if (!checked) {
print('collection '+green(collectionName)+' index '+green(existingIndex["name"])+' will be '+red('dropped'));
if (mode == LIVE) {
dbCollection.dropIndex(existingIndex["name"]);
}
}
}
}
if (mode == LIVE) {
print('Completed! '+magenta('LIVE MODE. All Operatoins are applied on database!'));
}
else {
print('Completed! '+cyan('TEST MODE. Nothing is applied.'));
}
}
function createIndex(db, name, indexItem) {
let options = {'name': name};
let key = indexItem['key'];
if('expireAfterSeconds' in indexItem) {
options['expireAfterSeconds'] = indexItem['expireAfterSeconds'];
}
if('background' in indexItem) {
options['background'] = indexItem['background'];
}
if('unique' in indexItem) {
options['unique'] = indexItem['unique'];
}
if('collation' in indexItem) {
options['collation'] = indexItem['collation'];
}
db.createIndex(key, options);
}
function isSameKey(existingIndex, newIndex) {
let key = existingIndex['key'];
let newKey = newIndex['key'];
// -2: v, ns
if (Object.keys(existingIndex).length -2 != Object.keys(newIndex).length) {
return false;
}
if (Object.keys(key).length != Object.keys(newKey).length) {
return false;
}
for(let i in key) {
let val = key[i];
if(i in newKey) {
if(newKey[i] != val) {
return false;
}
}
else {
return false;
}
}
let except = ['v', 'ns', 'key'];
for (let element in existingIndex) {
if (except.indexOf(element) >= 0) {
continue;
}
if (existingIndex[element] != newIndex[element]) {
let a = existingIndex[element];
let b = newIndex[element];
if (isObject(a) && isObject(b)) {
print(element)
for (let el in b) {
if (a[el] != b[el]) {
return false;
}
}
return true;
}
return false;
}
}
return true;
}
function isObject(val) {
if (val === null) { return false;}
return ( (typeof val === 'function') || (typeof val === 'object') );
}
// colors
function red (text) { return colorize(text, 'red') }
function green (text) { return colorize(text, 'green') }
function yellow (text) { return colorize(text, 'yellow') }
function blue (text) { return colorize(text, 'blue') }
function magenta (text) { return colorize(text, 'magenta') }
function cyan (text) { return colorize(text, 'cyan') }
function gray (text) { return colorize(text, 'gray') }
function colorize(text, color, style) {
// color: 'red', 'green', 'blue'... (see below)
// styles: 'normal' or undefined, 'bright', 'highlight'
if (!style) {
style = 'normal';
}
let _ansi = {
csi: String.fromCharCode(0x1B) + '[',
reset: '0',
text_prop: 'm',
styles: {
normal: '3',
bright: '9',
highlight: '4'
},
colors: {
black: '0',
red: '1',
green: '2',
yellow: '3',
blue: '4',
magenta: '5',
cyan: '6',
gray: '7'
}
};
let beginColor = _ansi.csi + _ansi.styles[style] + _ansi.colors[color] + _ansi.text_prop;
let endColor = _ansi.csi + _ansi.reset + _ansi.text_prop;
return beginColor + text + endColor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment