AWS DocumnetDB匯出到社區版Mongodb
在遷移時遇到 DocumentDB 匯出時的*.metadata.json會有參雜獨有的參數,造成社區版匯入時的異常。

處理辦法
主要是透過 js 將所有metadata.json 裡面含有這段參數的都移除,就能順利透過mongorestore
匯入Mongodb。
為了快速啟用服務,這邊會使用Docker 。
docker run --name mongodb-temp -v ./:/temp mongo:5.0.31-focal
docker exec -it mongodb-temp bash
放入了些常用工具以及等等要運行的node 環境,可以進行一鍵安裝。
apt update
apt install zip unzip vim bash curl -y
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bashrc && echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.bashrc
source ~/.bashrc
nvm install 20
匯出
#!/bin/bash
MONGO_HOST=""
MONGO_PORT="27017"
MONGO_USERNAME=""
MONGO_PASSWORD=""
mongodump --host=$MONGO_HOST \
--port=$MONGO_PORT \
--username=$MONGO_USERNAME \
--password=$MONGO_PASSWORD
匯入
#!/bin/bash
#mongodb version 6
MONGO_USERNAME="root"
MONGO_PASSWORD=""
MONGO_AUTH_DB="admin"
MONGO_HOST=""
MONGO_PORT=""
TARGET_DB="xxx_db"
DUMP_PATH="./xxxx"
mongorestore --username=$MONGO_USERNAME \
--password=$MONGO_PASSWORD \
--authenticationDatabase=$MONGO_AUTH_DB \
--nsInclude="$TARGET_DB.*" \
--host=$MONGO_HOST \
--port=$MONGO_PORT \
$DUMP_PATH
#!/bin/bash
#mongodb version 5
MONGO_USERNAME="root"
MONGO_PASSWORD=""
MONGO_AUTH_DB="admin"
MONGO_HOST=""
MONGO_PORT=""
TARGET_DB="xxx_db"
DUMP_PATH="./xxxx"
mongorestore --username=$MONGO_USERNAME \
--password=$MONGO_PASSWORD \
--authenticationDatabase=$MONGO_AUTH_DB \
--db=$TARGET_DB \
--host=$MONGO_HOST \
--port=$MONGO_PORT \
$DUMP_PATH
js 移除meta數據源
node test.js dump/
const fs = require('fs');
const path = require('path');
/**
* 修复DocumentDB导出的元数据文件以兼容MongoDB社区版
* @param {string} directoryPath - 包含导出数据的目录路径
*/
function fixMetadataFiles(directoryPath) {
console.log(`开始处理目录: ${directoryPath}`);
// 递归遍历目录
function processDirectory(dirPath) {
const items = fs.readdirSync(dirPath);
for (const item of items) {
const itemPath = path.join(dirPath, item);
const stats = fs.statSync(itemPath);
if (stats.isDirectory()) {
// 如果是目录,递归处理
processDirectory(itemPath);
} else if (stats.isFile() && item.endsWith('.metadata.json')) {
// 如果是元数据文件,进行修复
fixMetadataFile(itemPath);
}
}
}
// 修复单个元数据文件
function fixMetadataFile(filePath) {
console.log(`处理文件: ${filePath}`);
try {
// 读取元数据文件
const content = fs.readFileSync(filePath, 'utf8');
const metadata = JSON.parse(content);
// 移除DocumentDB特有的设置
if (metadata.options && metadata.options.storageEngine &&
metadata.options.storageEngine.documentDB) {
console.log(` - 移除storageEngine设置`);
delete metadata.options.storageEngine;
}
// 处理索引兼容性问题
if (metadata.indexes && Array.isArray(metadata.indexes)) {
let indexesFixed = false;
metadata.indexes = metadata.indexes.map(index => {
// 移除background选项
if (index.background) {
delete index.background;
indexesFixed = true;
}
return index;
});
if (indexesFixed) {
console.log(` - 修复索引设置`);
}
}
// 写回修复后的元数据
fs.writeFileSync(filePath, JSON.stringify(metadata, null, 2));
console.log(` ✓ 文件已修复`);
} catch (error) {
console.error(` ✗ 处理文件时出错: ${error.message}`);
}
}
// 开始处理
processDirectory(directoryPath);
console.log('所有元数据文件处理完成');
}
// 如果直接运行此脚本
if (require.main === module) {
// 获取命令行参数
const args = process.argv.slice(2);
if (args.length === 0) {
console.error('错误: 请提供包含导出数据的目录路径');
console.log('用法: node fix_metadata_files.js <导出目录路径>');
process.exit(1);
}
const directoryPath = args[0];
// 检查目录是否存在
if (!fs.existsSync(directoryPath) || !fs.statSync(directoryPath).isDirectory()) {
console.error(`错误: 目录 "${directoryPath}" 不存在或不是有效目录`);
process.exit(1);
}
fixMetadataFiles(directoryPath);
}
module.exports = { fixMetadataFiles };