V 2.0.0 ferige Version
This commit is contained in:
184
scripts/migrate-mongo-to-mysql.mjs
Normal file
184
scripts/migrate-mongo-to-mysql.mjs
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* MongoDB-Export → MySQL Migration
|
||||
*
|
||||
* Liest eine NDJSON-Datei (mongoexport-Format, eine Zeile = ein Dokument)
|
||||
* und importiert alle Einträge in die MySQL-Tabelle.
|
||||
*
|
||||
* Konfiguration via Umgebungsvariablen oder direkt hier eintragen:
|
||||
*
|
||||
* IMPORT_FILE Pfad zur Exportdatei (default: ~/Downloads/spritzschema_a)
|
||||
* MYSQLHOST MySQL-Host (default: localhost)
|
||||
* MYSQLPORT MySQL-Port (default: 3306)
|
||||
* MYSQLUSER MySQL-Benutzer (default: root)
|
||||
* MYSQLPASSWORD MySQL-Passwort (default: leer)
|
||||
* MYSQLBASE MySQL-Datenbank (default: medizin)
|
||||
* MYSQL_TABLE MySQL-Tabellenname (default: spritzschema)
|
||||
*
|
||||
* Aufruf:
|
||||
* node scripts/migrate-mongo-to-mysql.mjs
|
||||
* IMPORT_FILE=/pfad/zur/datei node scripts/migrate-mongo-to-mysql.mjs
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import mysql from 'mysql2/promise';
|
||||
|
||||
// ── .env.local laden (falls vorhanden) ────────────────────────
|
||||
const envFile = path.resolve(process.cwd(), '.env.local');
|
||||
if (fs.existsSync(envFile)) {
|
||||
for (const line of fs.readFileSync(envFile, 'utf-8').split('\n')) {
|
||||
const m = line.match(/^\s*([A-Z_]+)\s*=\s*(.*)\s*$/);
|
||||
if (m && !process.env[m[1]]) process.env[m[1]] = m[2].replace(/^['"]|['"]$/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Konfiguration ──────────────────────────────────────────────
|
||||
const IMPORT_FILE = process.env.IMPORT_FILE
|
||||
|| path.join(os.homedir(), 'Downloads', 'spritzschema_a');
|
||||
|
||||
const MYSQLHOST = process.env.MYSQLHOST || 'localhost';
|
||||
const MYSQLPORT = parseInt(process.env.MYSQLPORT || '3306');
|
||||
const MYSQLUSER = process.env.MYSQLUSER || 'root';
|
||||
const MYSQLPASSWORD = process.env.MYSQLPASSWORD || '';
|
||||
const MYSQLBASE = process.env.MYSQLBASE || 'medizin';
|
||||
const MYSQL_TABLE = process.env.MYSQL_TABLE || 'spritzschema';
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
|
||||
async function ensureTable(conn) {
|
||||
await conn.query(`
|
||||
CREATE TABLE IF NOT EXISTS \`${MYSQL_TABLE}\` (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
curdate VARCHAR(20) NOT NULL UNIQUE,
|
||||
months JSON NOT NULL,
|
||||
years JSON NOT NULL,
|
||||
data JSON NOT NULL,
|
||||
einheit INT NOT NULL DEFAULT 0,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
}
|
||||
|
||||
function normalizeDoc(doc) {
|
||||
// einheit in data-Items kann String oder Number sein → immer Int
|
||||
const data = (Array.isArray(doc.data) ? doc.data : []).map((item) => ({
|
||||
...item,
|
||||
einheit: parseInt(item.einheit) || 0,
|
||||
}));
|
||||
return {
|
||||
curdate: doc.curdate ?? '',
|
||||
months: Array.isArray(doc.months) ? doc.months : [],
|
||||
years: Array.isArray(doc.years) ? doc.years : [],
|
||||
data,
|
||||
einheit: parseInt(doc.einheit) || 0,
|
||||
};
|
||||
}
|
||||
|
||||
async function readExportFile(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
||||
// Unterstützt beide Formate: JSON-Array [...] und NDJSON (eine Zeile = ein Dokument)
|
||||
if (content.startsWith('[')) {
|
||||
return JSON.parse(content);
|
||||
}
|
||||
// NDJSON-Fallback
|
||||
const docs = [];
|
||||
let lineNo = 0;
|
||||
for (const line of content.split('\n')) {
|
||||
lineNo++;
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) continue;
|
||||
try {
|
||||
docs.push(JSON.parse(trimmed));
|
||||
} catch (e) {
|
||||
console.warn(` SKIP Zeile ${lineNo}: Kein gültiges JSON (${e.message})`);
|
||||
}
|
||||
}
|
||||
return docs;
|
||||
}
|
||||
|
||||
async function migrate() {
|
||||
// ── Exportdatei lesen ──
|
||||
console.log(`Lese Exportdatei: ${IMPORT_FILE}`);
|
||||
if (!fs.existsSync(IMPORT_FILE)) {
|
||||
console.error(`FEHLER: Datei nicht gefunden: ${IMPORT_FILE}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const docs = await readExportFile(IMPORT_FILE);
|
||||
console.log(` ${docs.length} Dokument(e) eingelesen.`);
|
||||
|
||||
if (docs.length === 0) {
|
||||
console.log('Nichts zu migrieren.');
|
||||
return;
|
||||
}
|
||||
|
||||
// ── MySQL verbinden ──
|
||||
console.log(`MySQL verbinden: ${MYSQLHOST}:${MYSQLPORT} / ${MYSQLBASE}`);
|
||||
const conn = await mysql.createConnection({
|
||||
host: MYSQLHOST,
|
||||
port: MYSQLPORT,
|
||||
user: MYSQLUSER,
|
||||
password: MYSQLPASSWORD,
|
||||
database: MYSQLBASE,
|
||||
});
|
||||
|
||||
await ensureTable(conn);
|
||||
console.log(` Tabelle '${MYSQL_TABLE}' bereit.`);
|
||||
|
||||
let inserted = 0;
|
||||
let updated = 0;
|
||||
let errors = 0;
|
||||
|
||||
for (const doc of docs) {
|
||||
const row = normalizeDoc(doc);
|
||||
|
||||
if (!row.curdate) {
|
||||
console.warn(` SKIP: Dokument ohne curdate (_id=${doc._id})`);
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const [result] = await conn.query(
|
||||
`INSERT INTO \`${MYSQL_TABLE}\` (curdate, months, years, data, einheit)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
months = VALUES(months),
|
||||
years = VALUES(years),
|
||||
data = VALUES(data),
|
||||
einheit = VALUES(einheit),
|
||||
updated_at = CURRENT_TIMESTAMP`,
|
||||
[
|
||||
row.curdate,
|
||||
JSON.stringify(row.months),
|
||||
JSON.stringify(row.years),
|
||||
JSON.stringify(row.data),
|
||||
row.einheit,
|
||||
]
|
||||
);
|
||||
// affectedRows=1 → INSERT, affectedRows=2 → UPDATE (ON DUPLICATE KEY)
|
||||
if (result.affectedRows === 1) {
|
||||
console.log(` INSERT curdate=${row.curdate}`);
|
||||
inserted++;
|
||||
} else {
|
||||
console.log(` UPDATE curdate=${row.curdate}`);
|
||||
updated++;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(` FEHLER curdate=${row.curdate}: ${e.message}`);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
await conn.end();
|
||||
|
||||
console.log('\n── Ergebnis ──────────────────────────');
|
||||
console.log(` Inserted : ${inserted}`);
|
||||
console.log(` Updated : ${updated}`);
|
||||
console.log(` Errors : ${errors}`);
|
||||
console.log(` Gesamt : ${docs.length}`);
|
||||
}
|
||||
|
||||
migrate().catch((err) => {
|
||||
console.error('Fataler Fehler:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user