Created
April 1, 2022 16:06
-
-
Save mdashti/8348044d001d4fffece3ea9403eaa593 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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