// ======= CONFIG: list your base collections here =======
const targetCollections = [
];
// ======= UTILITIES =======
function collExists(name) {
return db.getCollectionInfos({ name }).length > 0;
}
function countOrZero(name) {
if (!collExists(name)) return 0;
// Accurate count; if you prefer faster (approx) use estimatedDocumentCount()
return db.getCollection(name).countDocuments({});
}
function pad(str, len) {
const s = String(str);
return s + " ".repeat(Math.max(0, len - s.length));
}
// ======= RUN =======
const header =
"Collection".padEnd(28) +
"original".padEnd(12) +
"duplicated_".padEnd(14) +
"backup_".padEnd(12) +
"backup_new_apps_".padEnd(18);
print(header);
print("-".repeat(header.length));
let totalOriginal = 0;
let totalDuplicated = 0;
let totalBackup = 0;
let totalBackupNewApps = 0;
for (const base of targetCollections) {
const originalName = base;
const duplicatedName = `duplicated_${base}`;
const backupName = `backup_${base}`;
const backupNewAppsName = `backup_new_apps_${base}`;
const cOriginal = countOrZero(originalName);
const cDup = countOrZero(duplicatedName);
const cBackup = countOrZero(backupName);
const cBackupNew = countOrZero(backupNewAppsName);
totalOriginal += cOriginal;
totalDuplicated += cDup;
totalBackup += cBackup;
totalBackupNewApps += cBackupNew;
print(
pad(base, 28) +
pad(cOriginal, 12) +
pad(cDup, 14) +
pad(cBackup, 12) +
pad(cBackupNew, 18)
);
}
print("-".repeat(header.length));
print(
pad("TOTAL", 28) +
pad(totalOriginal, 12) +
pad(totalDuplicated, 14) +
pad(totalBackup, 12) +
pad(totalBackupNewApps, 18)
);
update collection
// mongosh — append "test" to IDs in duplicated_* collections
// - duplicated_application: applicationId += "test", tokenizedApplicationId += "test"
// - others (creditDecisioning, consentData, task, document, pricing, note, fraudDecisioning):
// applicationId += "test" only
// - Safe to re-run (no double-append)
//
// Requires MongoDB 4.2+ (pipeline updates).
const BASES = [
];
const SUFFIX = "test";
const APP_COLL_NAME = "duplicated_application";
const APP_ID_FIELD = "applicationId";
const TOK_APP_ID_FIELD = "tokenizedApplicationId";
function collExists(name) {
return db.getCollectionInfos({ name }).length > 0;
}
// Select docs where field exists, not null, and DOES NOT already end with SUFFIX
function notAlreadySuffixed(field, suffix) {
const q = {};
q[field] = { $exists: true, $ne: null, $not: new RegExp(`${suffix}$`) };
return q;
}
BASES.forEach((base) => {
const name = `duplicated_${base}`;
if (!collExists(name)) {
print(`\n[${name}] does not exist — skipping.`);
return;
}
const coll = db.getCollection(name);
print(`\n[${name}] updating…`);
if (name === APP_COLL_NAME) {
// 1) applicationId += "test"
const q1 = notAlreadySuffixed(APP_ID_FIELD, SUFFIX);
const r1 = coll.updateMany(
q1,
[
{
$set: {
[APP_ID_FIELD]: { $concat: [{ $toString: `$${APP_ID_FIELD}` }, SUFFIX] },
},
},
]
);
// 2) tokenizedApplicationId += "test" (ONLY for duplicated_application)
const q2 = notAlreadySuffixed(TOK_APP_ID_FIELD, SUFFIX);
const r2 = coll.updateMany(
q2,
[
{
$set: {
[TOK_APP_ID_FIELD]: { $concat: [{ $toString: `$${TOK_APP_ID_FIELD}` }, SUFFIX] },
},
},
]
);
print(` ${APP_ID_FIELD}: matched=${r1.matchedCount}, modified=${r1.modifiedCount}`);
print(` ${TOK_APP_ID_FIELD}: matched=${r2.matchedCount}, modified=${r2.modifiedCount}`);
} else {
// Other duplicated_* collections: ONLY applicationId
const q = notAlreadySuffixed(APP_ID_FIELD, SUFFIX);
const r = coll.updateMany(
q,
[
{
$set: {
[APP_ID_FIELD]: { $concat: [{ $toString: `$${APP_ID_FIELD}` }, SUFFIX] },
},
},
]
);
print(` ${APP_ID_FIELD}: matched=${r.matchedCount}, modified=${r.modifiedCount}`);
}
});
print("\nDone.");
create index
// Create empty duplicated_<collection> and add a unique index on applicationId
const BASES = [
];
function collExists(name) {
return db.getCollectionInfos({ name }).length > 0;
}
BASES.forEach((base) => {
const dupName = `duplicated_${base}`;
print(`\n=== ${dupName} ===`);
if (!collExists(dupName)) {
db.createCollection(dupName);
print(`Created collection ${dupName}`);
} else {
print(`${dupName} already exists (skipping creation)`);
}
// Ensure unique index on applicationId
const idx = db.getCollection(dupName).createIndex(
{ applicationId: 1 },
{ unique: true, name: "uniq_applicationId" }
);
print(`Index ensured: ${idx}`);
});
print("\nDone.");
delete and repopulate
// Transfer docs from duplicated_, backup_new_apps_, backup_ INTO original collections using $merge
// Fast (server-side), idempotent (upsert), no index drops.
//
// === CONFIG ===
const BASES = [
];
// Merge sources in this priority/order. Later sources can overwrite earlier ones if same key.
const SOURCES = ["duplicated_", "backup_new_apps_", "backup_"];
// Match key for upsert. Typically "_id". If backups were created with original _id, keep "_id".
// If you need to match by applicationId instead, set: const MATCH_ON = "applicationId";
const MATCH_ON = "_id";
// Optional: set to true to just print the plan without executing merges
const DRY_RUN = false;
// === HELPERS ===
function collExists(name) {
return db.getCollectionInfos({ name }).length > 0;
}
function mergeOne(srcName, destName, matchOn) {
if (!collExists(srcName)) {
print(` - ${srcName} (missing) — skip`);
return;
}
const pipeline = [
{ $match: {} },
{
$merge: {
into: destName,
on: matchOn, // "_id" or "applicationId"
whenMatched: "replace", // overwrite destination doc
whenNotMatched: "insert", // insert new
}
}
];
print(` > merging ${srcName} -> ${destName} ON "${matchOn}" ...`);
if (DRY_RUN) return;
db.getCollection(srcName).aggregate(pipeline, { allowDiskUse: true });
print(` done.`);
}
// === RUN ===
BASES.forEach((base) => {
const dest = base;
print(`\n=== ${dest} ===`);
SOURCES.forEach((prefix) => {
const src = `${prefix}${base}`;
mergeOne(src, dest, MATCH_ON);
});
});
print("\nAll merges complete.");
const NOW_ISO_UTC = "2025-09-21T18:06:17Z";
Top comments (0)