Skip to content

Instantly share code, notes, and snippets.

@mdashti
Created April 1, 2022 16:06
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 mdashti/8348044d001d4fffece3ea9403eaa593 to your computer and use it in GitHub Desktop.
Save mdashti/8348044d001d4fffece3ea9403eaa593 to your computer and use it in GitHub Desktop.
function generateRandomString(length) {
var randomString = ''
while (randomString.length < length) {
randomString += Math.random().toString(20).slice(2, length);
if (randomString.length > length) return randomString.slice(0, length);
}
return randomString;
};
function generateRandomInt(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min)
}
const {MongoClient} = require('mongodb');
const Db = require('mongodb/lib/db');
const isDebugMode = false;
const numExperiments = 10000;
const connectionUrl = 'mongodb://localhost:27017'
const dbName = 'myTestDB'
const srcCollName = "srcColl";
const matViewCollName = "matViewColl";
const numDocs = 100000;
let client
let db
let adminDb
const init = () => MongoClient.connect(connectionUrl, {useNewUrlParser: true})
.then((theClient) => {
client = theClient;
adminDb = client.db('admin')
db = client.db(dbName);
})
async function runTest() {
let coll = db.collection(srcCollName);
console.log('Started preparation.');
// Remove previous data.
await db.collection(srcCollName).drop();
await db.collection(matViewCollName).drop();
// Insert some control documents.
let data = []
for (var i = 0; i < numDocs; ++i) {
data.push({
'_id': i+100,
't': generateRandomInt(0, 10),
'y': generateRandomInt(0, 1000),
'w': generateRandomInt(0, 100),
'a': generateRandomString(16)
});
}
console.log('Created data.');
await coll.insertMany(data);
console.log('Inserted data.');
try {
console.log('Started running tests.');
let startTime = new Date();
for (var i = 0; i < numExperiments; ++i) {
if(isDebugMode) console.log('Running test ' + (i+1) + '...');
await runTestIteration(db, {debug: isDebugMode, sharded: false, transactional: false, updateView: true});
if(isDebugMode) console.log('---------------------------------------------');
}
let endTime = new Date();
let duration = endTime.getTime() - startTime.getTime();
console.log('Ran experiment in ' + duration + ' ms.');
console.log('Finished running tests.');
} catch (e) {
console.log('Errored while running tests.');
throw e;
}
}
async function printCollection(db, collName) {
let coll = db.collection(collName);
let arr = await coll.find().toArray()
console.log(collName + ' = ' + JSON.stringify(arr));
}
async function runTestIteration(db, options) {
let debug = options.debug;
let sharded = options.sharded;
let transactional = options.transactional;
let updateView = options.updateView;
let session = transactional ? client.startSession() : null;
function addSession(opts) {
if(transactional) {
opts.session = session;
}
return opts;
}
let matViewUpdateFn = async () => {
let coll = await db.collection(srcCollName);
if(debug) await printCollection(db, srcCollName);
await coll.updateOne({_id: 100 + generateRandomInt(0, numDocs-1)}, {$inc: { t: 2 }}, addSession({upsert: false, writeConcern: "majority"}));
if(debug) await printCollection(db, srcCollName);
if(updateView) {
const matViewTempCollName = "matViewTempColl"+generateRandomString(10);
await db.createCollection(matViewTempCollName, addSession({ writeConcern: "majority" }));
if(sharded) {
await adminDb.command({shardCollection: dbName+'.'+matViewTempCollName, key: {_id: 1}});
}
let matViewTempColl = await db.collection(matViewTempCollName);
if(debug) console.log('created collection ' + matViewTempCollName);
if(debug) await printCollection(db, matViewTempCollName);
let aggOutRes
if(!transactional) {
aggOutRes = await coll.aggregate([{$group: {_id: "$y", t_avg: { $avg : "$t" }, w_avg: { $avg : "$w" }}}, {$merge: {into: matViewTempCollName, on: '_id'}}], addSession({'allowDiskUse': true})).toArray();
} else {
aggOutRes = await coll.aggregate([{$group: {_id: "$y", t_avg: { $avg : "$t" }, w_avg: { $avg : "$w" }}}], addSession({'allowDiskUse': true})).toArray();
await matViewTempColl.insertMany(aggOutRes, addSession({ordered: false, writeConcern: "majority"}));
}
if(debug) console.log('The output keys for creating ' + matViewTempCollName + ' (using ' + srcCollName + ') = ' + JSON.stringify(aggOutRes));
if(debug) await printCollection(db, matViewTempCollName);
if(!transactional) {
await matViewTempColl.rename(matViewCollName, addSession({dropTarget: true}));
if(debug) await printCollection(db, matViewCollName);
if(debug) console.log("Done with transaction.")
}
}
}
if(transactional) {
await session.startTransaction();
try{
await matViewUpdateFn();
} catch(err) {
console.log(err);
} finally {
await session.commitTransaction();
await session.endSession();
}
} else {
await matViewUpdateFn();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment