|
|
@@ -0,0 +1,169 @@ |
|
|
/* |
|
|
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; |