Skip to content

Instantly share code, notes, and snippets.

@marpstar
Last active February 26, 2023 23:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marpstar/b257ceb628a428ec66aabde72c0cdbc4 to your computer and use it in GitHub Desktop.
Save marpstar/b257ceb628a428ec66aabde72c0cdbc4 to your computer and use it in GitHub Desktop.
Compare Two MongoDB Collections (even on different servers) in TypeScript
/**
* MIT License
* Copyright (c) 2023 Cody Sand
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
* This script compares two MongoDB collections and reports any differences.
*
* Credit for the workflow goes to @niccottrell (https://github.com/niccottrell)
* Original: https://gist.github.com/niccottrell/3ff2efc2146090aa8c5b73c1eb75ba2c
*
* This version uses the node `mongodb` package instead of the internal mongodb script engine.
*
* To launch and debug this inside of VSCode, use the "Run Script" launch configuration below
*
* {
* "name": "DB Diff",
* "type": "node",
* "request": "launch",
* "runtimeArgs": ["-r", "${workspaceFolder}/node_modules/ts-node/register/transpile-only"],
* "args": ["${workspaceFolder}/path/to/this/file//db-diff.ts"],
* "console": "integratedTerminal"
* }
*/
import { MongoClient } from "mongodb";
const runScript = async () => {
const uriOld =
"mongodb+srv://user:password@mongo.example.com";
const uriNew =
"mongodb+srv://user:password@mongo.example.com";
const dbNameOld = "old_db";
const dbNameNew = "new_db";
// connect to mongos
const connOld = await MongoClient.connect(uriOld);
const dbOld = connOld.db(dbNameOld);
const connNew = await MongoClient.connect(uriNew);
const dbNew = connNew.db(dbNameNew);
var collectionsToCheck = ["media"];
const oldCollections = await dbOld.collections();
oldCollections.forEach(async function (collname) {
const collectionName = collname.collectionName;
if (collectionsToCheck.includes(collectionName)) {
console.log("Checking " + collectionName);
// Check count and size first
const cstatsOld = await dbOld.command({ collStats: collectionName });
const cstatsNew = await dbNew.command({ collStats: collectionName });
if (cstatsOld.count === cstatsNew.count) {
console.log("Count " + cstatsOld.count + " OK");
} else {
console.log(
"ERR Count mismatch " + cstatsOld.count + " -> " + cstatsNew.count
);
}
if (cstatsOld.size === cstatsNew.size) {
console.log("Size " + cstatsOld.size + " OK");
} else {
console.log(
"ERR Size mismatch " + cstatsOld.size + " -> " + cstatsNew.size
);
}
let fails = 0;
const oldRecords = await dbOld
.collection(collectionName)
.find({})
.toArray();
await Promise.all(
oldRecords.map(async (docOld) => {
const docNew = await dbNew.collection(collectionName).findOne({
_id: docOld._id,
});
const stringOld = JSON.stringify(docOld);
const stringNew = JSON.stringify(docNew);
if (stringOld == stringNew) {
// console.log("Doc matches: " + docOld._id);
} else {
console.log("Doc mismatch: " + docOld._id);
// console.log("Old=", docOld);
// console.log("New=", docNew);
fails++;
}
})
);
if (fails > 0) {
console.log(fails + " fails");
} else {
console.log("All OK");
}
connOld.close();
connNew.close();
process.exit(0);
}
});
};
runScript();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment