nodiak
Version:
Nodiak is a Node.js client for the Riak Distributed Database
138 lines (115 loc) • 4.83 kB
JavaScript
// (The MIT License)
// Copyright (c) 2012 Coradine Aviation Systems
// Copyright (c) 2012 Nathan Aschbacher
// 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.
var events = require('events');
var Mapred = function Mapred(client) {
this._inputs = null;
this.include_data = false;
this.phases = [];
this.client = client;
};
Mapred.prototype.inputs = function(inputs, include_data) {
this._inputs = inputs;
this.include_data = include_data;
return this;
};
Mapred.prototype.link = function(phase) {
this.append('link', phase);
return this;
};
Mapred.prototype.map = function(phase) {
this.append('map', phase);
return this;
};
Mapred.prototype.reduce = function(phase) {
this.append('reduce', phase);
return this;
};
Mapred.prototype.execute = function(_return) {
var stream_results = _return instanceof Function ? false : true;
var _this = this;
this._inputs = Mapred.filterInputs(this._inputs, this.include_data);
var options = {};
if(stream_results) options.chunked = true;
var query = {
path: this.client.defaults.resources.riak_kv_wm_mapred + "/",
headers: { "content-type": "application/json" },
body: { inputs: this._inputs, query: this.phases },
options: options
};
if(stream_results) { // If attempting a stream results.
return {
stream: function() {
var emitter = new events.EventEmitter();
_this.client.POST(query, function(err, result) {
if(err) {
err.data = result;
emitter.emit('error', err);
}
else {
if(result.hasOwnProperty('data')) {
result = _this.client.parseBody(result.data, result.metadata.content_type);
if(result.length !== 0) {
for(var i = 0, length = result.length; i < length; i++) {
var temp = _this.client.parseBody(result[i].data, result[i].metadata.content_type);
result[i].phase = temp.phase;
result[i].data = temp.data;
}
emitter.emit('data', result.length > 1 ? result : result[0]);
}
}
else {
emitter.emit('end');
emitter.removeAllListeners();
}
}
});
return emitter;
}
};
}
else { // Else not dealing with a stream
this.client.POST(query, _return);
}
return this;
};
Mapred.prototype.append = function(type, phase) {
var new_phase = {};
if(typeof(phase) == 'object' && phase.language && phase.language.toLowerCase() == 'javascript' && phase.source) {
phase.source = phase.source.toString();
}
else if(typeof(phase) == 'object' && phase.language && phase.language.toLowerCase() == 'erlang' && phase.source) {
phase.source = phase.source();
}
new_phase[type] = phase;
this.phases.push(new_phase);
};
Mapred.filterInputs = function(inputs, include_data) {
// Use this if...for to get raw keys out of RObjects
if(inputs instanceof Array && inputs.length > 0 && inputs[0].constructor.name == 'RObject') {
for(var i = 0, length = inputs.length; i < length; i++) {
inputs[i] = [inputs[i].bucket.name, inputs[i].key];
if(include_data) {
inputs[i].push(inputs[i].data);
}
}
}
return inputs;
};
module.exports = Mapred;