@khawer.ali/mongo-db-migrator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -0
- package/migrate.js +135 -0
- package/package.json +34 -0
- package/server/routes/migrateRoutes.js +10 -0
- package/server/server.js +21 -0
- package/server/services/migrateService.js +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Mongo DB Migrator
|
|
2
|
+
|
|
3
|
+
A powerful Node.js command-line tool for migrating MongoDB databases between servers. Perfect for copying production data to local development, server-to-server migrations, and database backups.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Full Database Migration** - Migrate all collections from a database
|
|
8
|
+
- ✅ **Single Collection Migration** - Migrate specific collections only
|
|
9
|
+
- ✅ **Remote & Local MongoDB Support** - Works with any MongoDB instance
|
|
10
|
+
- ✅ **Real-time Progress Tracking** - See migration progress as it happens
|
|
11
|
+
- ✅ **Batch Processing** - Efficiently handles large datasets
|
|
12
|
+
- ✅ **Error Handling** - Robust error reporting and connection management
|
|
13
|
+
- ✅ **CLI Interactive Mode** - User-friendly prompts
|
|
14
|
+
- ✅ **Command Line Arguments** - Scriptable for automation
|
|
15
|
+
|
|
16
|
+
## 📦 Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Clone the repository
|
|
20
|
+
git clone https://github.com/alikhawer29/mongo-db-migrator
|
|
21
|
+
cd mongo-db-migrator
|
|
22
|
+
|
|
23
|
+
# Install dependencies
|
|
24
|
+
npm install
|
|
25
|
+
|
|
26
|
+
# Make the script executable (optional)
|
|
27
|
+
chmod +x migrate.js
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 🛠️ Usage
|
|
31
|
+
|
|
32
|
+
### Interactive Mode (Recommended)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run migrate
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This will prompt you for:
|
|
39
|
+
- Source MongoDB URI
|
|
40
|
+
- Target MongoDB URI
|
|
41
|
+
- Database name
|
|
42
|
+
- Collection name (optional - leave empty for all collections)
|
|
43
|
+
|
|
44
|
+
### Command Line Arguments
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
node migrate.js "source-uri" "target-uri" "database-name" "collection-name"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Examples
|
|
51
|
+
|
|
52
|
+
#### Migrate Entire Database
|
|
53
|
+
```bash
|
|
54
|
+
npm run migrate
|
|
55
|
+
# Follow prompts to enter connection details
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Migrate Specific Collection
|
|
59
|
+
```bash
|
|
60
|
+
node migrate.js "mongodb://admin:password@source.com:27017/" "mongodb://target.com:27017/" "mydb" "users"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Production to Local Development
|
|
64
|
+
```bash
|
|
65
|
+
node migrate.js "mongodb://admin:password@source-mongodb.com:27017/" "mongodb://localhost:27017/" "mydb" ""
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 📋 MongoDB URI Format
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
mongodb://[username:password@]host[:port]/[database]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Examples:
|
|
75
|
+
- **Local**: `mongodb://localhost:27017/`
|
|
76
|
+
- **With Auth**: `mongodb://admin:password@host:27017/`
|
|
77
|
+
- **Atlas Cloud**: `mongodb://user:pass@cluster.mongodb.net/`
|
|
78
|
+
|
|
79
|
+
## 🎯 Recent Migration Success
|
|
80
|
+
|
|
81
|
+
The tool successfully migrated a production database with 21 collections:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
📊 Migration Summary:
|
|
85
|
+
- Source: source-mongodb.com:27017
|
|
86
|
+
- Target: target-mongodb.com:28028
|
|
87
|
+
- Database: ltest
|
|
88
|
+
- Collections: 21 total
|
|
89
|
+
- Documents: 323 migrated
|
|
90
|
+
- Duration: ~2 minutes
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Collections Migrated:
|
|
94
|
+
- `users` (45 documents)
|
|
95
|
+
- `notifications` (114 documents)
|
|
96
|
+
- `payments` (26 documents)
|
|
97
|
+
- `chatmessages` (27 documents)
|
|
98
|
+
- `bookings` (26 documents)
|
|
99
|
+
- And 16 more collections...
|
|
100
|
+
|
|
101
|
+
## 🔧 Configuration
|
|
102
|
+
|
|
103
|
+
No configuration required! The tool works out of the box. Simply provide the MongoDB connection URIs when prompted.
|
|
104
|
+
|
|
105
|
+
## 🚨 Requirements
|
|
106
|
+
|
|
107
|
+
- Node.js 14+
|
|
108
|
+
- MongoDB Node.js Driver (included)
|
|
109
|
+
- Access to source and target MongoDB databases
|
|
110
|
+
|
|
111
|
+
## 🐛 Troubleshooting
|
|
112
|
+
|
|
113
|
+
### "Found 0 collections"
|
|
114
|
+
- Check database name spelling (case-sensitive)
|
|
115
|
+
- Verify database exists on source server
|
|
116
|
+
- Ensure proper authentication credentials
|
|
117
|
+
|
|
118
|
+
### Connection Issues
|
|
119
|
+
- Verify MongoDB URI format
|
|
120
|
+
- Check network connectivity
|
|
121
|
+
- Ensure MongoDB is running on target server
|
|
122
|
+
- Validate username/password credentials
|
|
123
|
+
|
|
124
|
+
### Large Databases
|
|
125
|
+
- Tool uses batch processing (1000 documents per batch)
|
|
126
|
+
- Progress is shown in real-time
|
|
127
|
+
- Handles millions of documents efficiently
|
|
128
|
+
|
|
129
|
+
## 📝 Development
|
|
130
|
+
|
|
131
|
+
### Project Structure
|
|
132
|
+
```
|
|
133
|
+
mongo-db-migrator/
|
|
134
|
+
├── migrate.js # Main CLI migration script
|
|
135
|
+
├── package.json # Dependencies and scripts
|
|
136
|
+
├── server/ # Optional Express server
|
|
137
|
+
│ ├── services/
|
|
138
|
+
│ │ └── migrateService.js
|
|
139
|
+
│ └── routes/
|
|
140
|
+
│ └── migrateRoutes.js
|
|
141
|
+
└── README.md # This file
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Scripts
|
|
145
|
+
- `npm run migrate` - Run migration tool
|
|
146
|
+
- `npm run dev` - Start Express server (optional)
|
|
147
|
+
- `npm start` - Start Express server
|
|
148
|
+
|
|
149
|
+
## 🤝 Contributing
|
|
150
|
+
|
|
151
|
+
1. Fork the repository
|
|
152
|
+
2. Create a feature branch
|
|
153
|
+
3. Make your changes
|
|
154
|
+
4. Test thoroughly
|
|
155
|
+
5. Submit a pull request
|
|
156
|
+
|
|
157
|
+
## 📄 License
|
|
158
|
+
|
|
159
|
+
ISC License - Feel free to use this tool in your projects!
|
|
160
|
+
|
|
161
|
+
## 🆘 Support
|
|
162
|
+
|
|
163
|
+
If you encounter issues:
|
|
164
|
+
1. Check the troubleshooting section above
|
|
165
|
+
2. Verify your MongoDB connection strings
|
|
166
|
+
3. Ensure proper database permissions
|
|
167
|
+
4. Test with small collections first
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
**Built with ❤️ by Khawer Ali using Node.js and MongoDB Driver**
|
|
172
|
+
|
|
173
|
+
Perfect for developers who need to migrate databases between environments quickly and safely!
|
package/migrate.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { MongoClient } = require("mongodb");
|
|
4
|
+
const readline = require('readline');
|
|
5
|
+
|
|
6
|
+
const rl = readline.createInterface({
|
|
7
|
+
input: process.stdin,
|
|
8
|
+
output: process.stdout
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
function question(prompt) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
rl.question(prompt, resolve);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function migrateDatabase({ sourceUri, targetUri, dbName, collectionName }) {
|
|
18
|
+
const sourceClient = new MongoClient(sourceUri);
|
|
19
|
+
const targetClient = new MongoClient(targetUri);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
console.log("Connecting to source database...");
|
|
23
|
+
await sourceClient.connect();
|
|
24
|
+
console.log("Connected to source database.");
|
|
25
|
+
|
|
26
|
+
// List all databases to help with debugging
|
|
27
|
+
const admin = sourceClient.db().admin();
|
|
28
|
+
const databases = await admin.listDatabases();
|
|
29
|
+
console.log("Available databases on source:");
|
|
30
|
+
databases.databases.forEach(db => {
|
|
31
|
+
console.log(` - ${db.name} (${db.sizeOnDisk} bytes)`);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
console.log("Connecting to target database...");
|
|
35
|
+
await targetClient.connect();
|
|
36
|
+
console.log("Connected to target database.");
|
|
37
|
+
|
|
38
|
+
const sourceDb = sourceClient.db(dbName);
|
|
39
|
+
const targetDb = targetClient.db(dbName);
|
|
40
|
+
|
|
41
|
+
let collections = [];
|
|
42
|
+
|
|
43
|
+
if (collectionName) {
|
|
44
|
+
collections = [collectionName];
|
|
45
|
+
} else {
|
|
46
|
+
console.log("Fetching all collections from source database...");
|
|
47
|
+
collections = await sourceDb.listCollections().toArray();
|
|
48
|
+
collections = collections.map(col => col.name);
|
|
49
|
+
console.log(`Found ${collections.length} collections: ${collections.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const collection of collections) {
|
|
53
|
+
console.log(`\nMigrating collection: ${collection}`);
|
|
54
|
+
|
|
55
|
+
const sourceCollection = sourceDb.collection(collection);
|
|
56
|
+
const targetCollection = targetDb.collection(collection);
|
|
57
|
+
|
|
58
|
+
// Get total documents count
|
|
59
|
+
const totalDocs = await sourceCollection.countDocuments();
|
|
60
|
+
console.log(`Total documents in ${collection}: ${totalDocs}`);
|
|
61
|
+
|
|
62
|
+
if (totalDocs === 0) {
|
|
63
|
+
console.log(`Collection ${collection} is empty, skipping...`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Create cursor for batch processing
|
|
68
|
+
const cursor = sourceCollection.find({});
|
|
69
|
+
let processedDocs = 0;
|
|
70
|
+
const batchSize = 1000;
|
|
71
|
+
let batch = [];
|
|
72
|
+
|
|
73
|
+
console.log("Starting migration...");
|
|
74
|
+
|
|
75
|
+
for await (const doc of cursor) {
|
|
76
|
+
batch.push(doc);
|
|
77
|
+
processedDocs++;
|
|
78
|
+
|
|
79
|
+
// Insert batch when it reaches batch size or when we finish
|
|
80
|
+
if (batch.length === batchSize || processedDocs === totalDocs) {
|
|
81
|
+
if (batch.length > 0) {
|
|
82
|
+
await targetCollection.insertMany(batch);
|
|
83
|
+
console.log(`Progress: ${processedDocs}/${totalDocs} documents (${Math.round((processedDocs/totalDocs)*100)}%)`);
|
|
84
|
+
batch = [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`✅ Successfully migrated ${processedDocs} documents from ${collection}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log("\n🎉 Migration completed successfully!");
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error("❌ Migration failed:", error.message);
|
|
96
|
+
} finally {
|
|
97
|
+
await sourceClient.close();
|
|
98
|
+
await targetClient.close();
|
|
99
|
+
rl.close();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
console.log("=== MongoDB Database Migration Tool ===\n");
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const sourceUri = await question("Enter source MongoDB URI: ");
|
|
108
|
+
const targetUri = await question("Enter target MongoDB URI: ");
|
|
109
|
+
const dbName = await question("Enter database name: ");
|
|
110
|
+
const collectionInput = await question("Enter collection name (leave empty for all collections): ");
|
|
111
|
+
|
|
112
|
+
const collectionName = collectionInput.trim() === '' ? null : collectionInput.trim();
|
|
113
|
+
|
|
114
|
+
console.log("\nStarting migration...");
|
|
115
|
+
console.log(`Source: ${sourceUri}`);
|
|
116
|
+
console.log(`Target: ${targetUri}`);
|
|
117
|
+
console.log(`Database: ${dbName}`);
|
|
118
|
+
console.log(`Collection: ${collectionName || 'All collections'}`);
|
|
119
|
+
console.log("\n" + "=".repeat(50));
|
|
120
|
+
|
|
121
|
+
await migrateDatabase({ sourceUri, targetUri, dbName, collectionName });
|
|
122
|
+
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error("Error:", error.message);
|
|
125
|
+
rl.close();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Also support command line arguments
|
|
130
|
+
if (process.argv.length > 2) {
|
|
131
|
+
const [, , sourceUri, targetUri, dbName, collectionName] = process.argv;
|
|
132
|
+
migrateDatabase({ sourceUri, targetUri, dbName, collectionName: collectionName || null });
|
|
133
|
+
} else {
|
|
134
|
+
main();
|
|
135
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@khawer.ali/mongo-db-migrator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to migrate MongoDB databases between servers",
|
|
5
|
+
"main": "migrate.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mongo-db-migrator": "./migrate.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"mongodb",
|
|
11
|
+
"migration",
|
|
12
|
+
"database",
|
|
13
|
+
"mongo",
|
|
14
|
+
"backup",
|
|
15
|
+
"cli",
|
|
16
|
+
"migrate"
|
|
17
|
+
],
|
|
18
|
+
"author": "Khawer Ali",
|
|
19
|
+
"license": "ISC",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"migrate": "node migrate.js",
|
|
22
|
+
"dev": "nodemon server/server.js",
|
|
23
|
+
"start": "node server/server.js"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"cors": "^2.8.6",
|
|
27
|
+
"express": "^5.2.1",
|
|
28
|
+
"mongodb": "^7.1.0",
|
|
29
|
+
"socket.io": "^4.8.3"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"nodemon": "^3.1.14"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { migrateDatabase } = require("../services/migrateService");
|
|
2
|
+
|
|
3
|
+
module.exports = async (req, res, io) => {
|
|
4
|
+
try {
|
|
5
|
+
await migrateDatabase({ ...req.body, io });
|
|
6
|
+
res.json({ message: "Migration started" });
|
|
7
|
+
} catch (err) {
|
|
8
|
+
res.status(500).json({ error: err.message });
|
|
9
|
+
}
|
|
10
|
+
};
|
package/server/server.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const cors = require("cors");
|
|
3
|
+
const http = require("http");
|
|
4
|
+
const { Server } = require("socket.io");
|
|
5
|
+
|
|
6
|
+
const migrateRoutes = require("./routes/migrateRoutes");
|
|
7
|
+
|
|
8
|
+
const app = express();
|
|
9
|
+
app.use(cors());
|
|
10
|
+
app.use(express.json());
|
|
11
|
+
|
|
12
|
+
const server = http.createServer(app);
|
|
13
|
+
const io = new Server(server, {
|
|
14
|
+
cors: { origin: "*" }
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
app.use("/api/migrate", (req, res) => migrateRoutes(req, res, io));
|
|
18
|
+
|
|
19
|
+
server.listen(5000, () => {
|
|
20
|
+
console.log("Server running on port 5000");
|
|
21
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const { MongoClient } = require("mongodb");
|
|
2
|
+
|
|
3
|
+
async function migrateDatabase({
|
|
4
|
+
sourceUri,
|
|
5
|
+
targetUri,
|
|
6
|
+
dbName,
|
|
7
|
+
collectionName,
|
|
8
|
+
io
|
|
9
|
+
}) {
|
|
10
|
+
const sourceClient = new MongoClient(sourceUri);
|
|
11
|
+
const targetClient = new MongoClient(targetUri);
|
|
12
|
+
|
|
13
|
+
await sourceClient.connect();
|
|
14
|
+
await targetClient.connect();
|
|
15
|
+
|
|
16
|
+
const sourceDb = sourceClient.db(dbName);
|
|
17
|
+
const targetDb = targetClient.db(dbName);
|
|
18
|
+
|
|
19
|
+
let collections = [];
|
|
20
|
+
|
|
21
|
+
if (collectionName) {
|
|
22
|
+
collections = [collectionName];
|
|
23
|
+
} else {
|
|
24
|
+
const list = await sourceDb.listCollections().toArray();
|
|
25
|
+
collections = list.map(c => c.name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for (const name of collections) {
|
|
29
|
+
const sourceCollection = sourceDb.collection(name);
|
|
30
|
+
const targetCollection = targetDb.collection(name);
|
|
31
|
+
|
|
32
|
+
const docs = await sourceCollection.find({}).toArray();
|
|
33
|
+
|
|
34
|
+
if (docs.length) {
|
|
35
|
+
await targetCollection.insertMany(docs);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (io) {
|
|
39
|
+
io.emit("progress", {
|
|
40
|
+
collection: name,
|
|
41
|
+
count: docs.length
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(`Migrated ${name}: ${docs.length} records`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await sourceClient.close();
|
|
49
|
+
await targetClient.close();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { migrateDatabase };
|