DEV Community

LS
LS

Posted on

mongodb shell script counting

// ======= 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)
);

Enter fullscreen mode Exit fullscreen mode

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.");

Enter fullscreen mode Exit fullscreen mode

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.");

Enter fullscreen mode Exit fullscreen mode

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";

Enter fullscreen mode Exit fullscreen mode

Top comments (0)