Created
December 4, 2012 11:56
-
-
Save ronalstal/4203035 to your computer and use it in GitHub Desktop.
mongodb aggregate: Convert Aggregate Result To Collection
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
/* | |
convertAggregateResultToCollection (alias: carc) | |
Author: Ronald Stalder <[email protected]> | |
*/ | |
var convertAggregateResultToCollection = function (aggResult, options) { | |
// void function to supress output | |
var _v = function() {}; | |
// SET DEFAULT OPTIONS UNLESS SPECIFIED | |
// options = { | |
// | |
// "out" : name of the resulting collection, default: "out" | |
// | |
// "mode" : "replace" eventually existing "out" or create new one | |
// (default, will drop the collection first, | |
// then same as "append") | |
// "append" to existing collection using insert (see "key") | |
// "merge" into existing collection using update-upsert on key | |
// | |
// "key" : <field> use this field as "_id" for the documents | |
// in the "out" collection | |
// If the option "removeKey" is true, the <field> will | |
// be "renamed" to _id, by default it will be copied | |
// | |
// "objId" an existing "_id" field in the result will be renamed | |
// to the value of the "renameKey" option, | |
// or deleted if "removeKey" is true, | |
// in order to force the generation of an objectId | |
// | |
// "_id" Default behavior is to take the "_id" from the result. | |
// If it does not exist, an ObecjtId will automatically be | |
// generated (this will result in "merge" being an "append") | |
// | |
// "removeKey" : true or false, default=false. See above | |
// | |
// "renameKey" : (string) existing "_id" in the result will be renamed to this | |
// (see above). Default: "origId" | |
// | |
// "constFields" : array of {name:"name", value:"value"} pairs - default: empty array | |
// In the resuling document, a "name": value field will be | |
// inserted for each pair in this array | |
// | |
// "debug": 0 - (default) quiet | |
// 1 - print out some basic information | |
// 2 - print out some stuff for debugging | |
// 3 - print also the result of the aggregate | |
// } | |
if ( typeof options == 'undefined' ) var options = {}; | |
if ( typeof options.out == 'undefined' ) options.out = "out"; | |
if ( typeof options.mode == 'undefined' ) options.mode = "replace"; | |
if ( typeof options.key == 'undefined' ) options.key = "_id"; | |
if ( typeof options.removeKey == 'undefined' ) options.removeKey = false; | |
if ( typeof options.renameKey == 'undefined' ) options.renameKey = "origId"; | |
if ( typeof options.constFields == 'undefined' ) options.constFields = []; | |
if ( typeof options.debug == 'undefined' ) options.debug = 0; | |
var debug = options.debug; | |
if ( debug ) print ( "\n*** convertAggregateResultToCollection (carc) -- start\n" ); | |
if ( debug > 2 ) printjson( aggResult ); | |
if ( debug > 1 ) printjson( options ); | |
// check for valid aggregate result in first parameter | |
if ( typeof aggResult.result !== "object" ) { | |
print( "ERROR: first parameter must be a valid output of aggregate() !\nexitting function" ); | |
return false; | |
} | |
try { _v(aggResult.result[0]) } | |
catch(err) { | |
print( "ERROR: output of aggregate() is empty\nexitting function" ); | |
return false; | |
} | |
// set the output collection | |
var out = db.getCollection( options.out ); | |
if ( debug ) print( 'output collection: "' + out + '" output mode is: "'+options.mode+'"' ); | |
// drop it if in "replace" mode and switch to "append" | |
if ( options.mode === "replace" ) { | |
out.drop(); | |
options.mode = "append"; | |
if ( debug ) print( 'output collection dropped; switched to "append" mode' ); | |
} | |
var r = aggResult.result; | |
// DETERMINE _ID FOR OUT COLLECTION | |
// asking for _id but there isn't any: switch to "objId" | |
var txt = 'the "_id" of the resulting documents will be '; | |
if ( options.key === "_id" && typeof r[0]._id === "undefined" ) { | |
if ( debug > 1 ) print( 'no _id in result, using "objectId"' ); | |
options.key = "objId"; | |
} | |
// as a generated objectId | |
if ( options.key === "objId" ) { | |
if ( debug ) print( txt+'a generated objectId' ); | |
// from a field in the result | |
} else { | |
eval( "var _idField = r[0]."+options.key ); | |
var _idType = typeof _idField; | |
// check that given key field exists | |
if ( options.key !== "_id" && _idType === "undefined" ) { | |
print( "ERROR: given key field '"+options.key | |
+"' does not exist\nexitting function" ); | |
return false; | |
} | |
if ( debug ) { | |
if ( _idType === "object" ) { | |
print( txt+"the compound:"); | |
printjson( _idField ); | |
} else { | |
print( txt+"the key: "+_idField ); | |
} | |
} | |
} | |
// LOOP THE RESULTS AND CREATE THE DOCUMENTS | |
if ( debug ) print( 'processing ' + r.length + ' result records' ); | |
for ( var i in aggResult.result ) { | |
doc = aggResult.result[i]; | |
// set _id | |
if ( !(options.key === "_id" || options.key === "objId") ) { | |
// copy the key <field> to _id | |
eval( "_idField = doc."+options.key ); | |
doc._id = _idField; | |
// and eventually remove it | |
if ( options.removeKey ) delete _idField; | |
// if we want objectId and there is an existing _id | |
} else if ( options.key === "objId" | |
&& typeof doc._id !== 'undefined' ) { | |
// rename the _id, unless the removeKey option is set to true | |
if ( !options.removeKey ) eval( "doc."+options.renameKey+" = doc._id" ); | |
// delete the _id, so an objectId will be generated | |
delete doc._id; | |
} | |
// add constant Fields | |
for ( var j in options.constFields ) { | |
eval( "doc."+options.constFields[j].name+"='"+options.constFields[j].value+"'" ); | |
} | |
// insert or update-upsert | |
if ( options.mode === "append" ) { | |
out.insert( doc ); | |
} else { | |
// prepare update command for the "merge" | |
var updCmd = 'out.update({"_id":doc._id},{$set:{'; | |
// update set all field from the result | |
for ( var key in doc ) { | |
if ( key == "_id" ) continue; | |
updCmd += '"'+key+'": "'+doc[key]+'",' | |
} | |
updCmd += '}},{"upsert":true})'; | |
// execute it | |
eval( updCmd ); | |
} | |
if ( debug > 1 ) printjson( doc ); | |
} | |
if ( debug ) print ( "\n*** convertAggregateResultToCollection (carc) -- end\n" ); | |
} | |
// set the alias | |
var carc = convertAggregateResultToCollection; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment