A JavaScript data aggregation pipeline based on the MongoDB database's aggregation framework. https://riveragroup.github.io/mungedb-aggregate/
|
|
11 éve | |
|---|---|---|
| lib | 11 éve | |
| npm_scripts | 12 éve | |
| test | 11 éve | |
| .gitignore | 12 éve | |
| .jscheckstyleignore | 12 éve | |
| .jshintrc | 12 éve | |
| README.md | 12 éve | |
| mungedb-aggregate.js | 12 éve | |
| package.json | 12 éve |
A JavaScript data aggregation pipeline based on the MongoDB aggregation framework.
In general, this code is a port from the MongoDB C++ code (v2.4.0) to JavaScript.
MongoDB is awesome. JavaScript is awesome(ish). So we decided to put them together.
Now, with the ease of JavaScript and the power of the MongoDB aggregation pipeline, we can provide a single API for data munging, regardless of where execution occurs.
// REQUIRE STUFF
var assert = require("assert");
var aggregate = require("mungedb-aggregate");
// SETUP SOME VARIABLES
var inputs = [{val:1}, {val:2}, {val:3}, {val:4}, {val:5}],
pipeline = [
{$match:{
val: {$gte:3}
}},
{$project:{
square: {$multiply:["$val", "$val"]}
}}
];
// SINGLE INPUT USAGE
aggregate(pipeline, inputs, function(err, results){
assert.deepEqual(results, [{square:9}, {square:16}, {square:25}]); // look ma, no server!
});
// MULTI INPUT USAGE
var aggregator = aggregate(pipeline);
aggregator(inputs, function(err, results){
assert.deepEqual(results, [{square:9}, {square:16}, {square:25}]); // look ma, no server!
});
aggregator(inputs, function(err, results){
assert.deepEqual(results, [{square:9}, {square:16}, {square:25}]); // look ma, no server!
});
Main publics:
aggregate -- this is also the root of the package exportsversion -- The MongoDB version that this code representsgitVersion -- And, if you want to get really specific, the MongoDB git version that this code representsInner workings:
Cursor -- Used internally to go through data (by PipelineD and CursorDocumentSource)pipeline
Pipeline -- The pipeline handlerPipelineD -- The pipeline data reader helperFieldPath -- Represents a path to a field within a documentDocument -- Document helpers used throughout the codeValue -- Value helpers used throughout the codeaccumulators -- All of the Accumulator classes, which are used for $groupdocumentSources -- All of the DocumentSource classes, which are used as the top-level pipeline components / stagesexpressions -- All of the Expression classes, which are used as the building blocks for many things, but especially for $projectHere is a list of the major items where we have deviated from the MongoDB code and a little bit about why:
.cpp file in the MongoDB code but to keep things clean and separate they have been broken out into files named the same and only rarely is there more than one class within a single fileBSON vs JSON
BSON-specific code has become equivalent JSON-specific code since that's what we're working with (no need for needless conversions)addToBson... and other BSONObjBuilder-related methods that take in an instance to be modified but it's owned by the caller; in mungedb-aggregate we build a new Object and return it because it's simpler and that's how they're generally used anyhowDocument class
Document now provides static helpers rather than instance helpers to avoid unecessary boxing/unboxing since that seems to make more sense here (we treat any Object like a Document)Value class
Value now provides static helpers rather than instance helpers to avoid unecessary boxing/unboxing since that seems to make more sense here (we treat any Object like a `Value)Value#get{TYPE} methods have been renamed to Value.verify{TYPE} since that seemed to make more sense given what they're really doing for us as staticsValue.coerceToDate static returns a JavaScript Date object rather than milliseconds since that seems to make more sense where possibleExpression classes
Expression base classObjectCtx class no longer uses contants and bitmask flags, instead it takes an Object with similarly named Booleans; e.g., {isDocumentOk:true} rather than DOCUMENT_OKExpression{FOO} classes have all been renamed to {FOO}Expression to satisfy my naming OCD.{FOO}Expression classes do not provide create statics since calling new is easy enoughCompareExpression class doesn't provide any of it's various create{FOO} helpers so compensate I am just binding the appropriate args to the constructor to create a similar factoryDocumentSource classes
reset method for all document sources so that we can reuse them against different streams of dataElementPath
isAllDigits: ElementPath.isAllDigits ( now static function )elementPath iteration: This is now encapsulated inside the elementPath class as a static method. It needs an input function to check the item at the end of the path.Status return
debugString
.get(), .release(), and .reset() methods
Here is a list of global items that I know about that may need to be done in the future:
assert.equal() calls into assert.strictEqual() callsseal, freeze, etc.) where appropriatevirtuals (i.e., /virtual .* = 0;$/) are implemented as a proto with a throw new Error("NOT IMPLEMENTED BY INHERITOR") or similarthrow and make them actually use UserException vs SystemException (or whatever they're called)sift package to fake the MatchDocumentSource class but need to actually port the real codePipelineD entirely here; might be more confusing than helpful and can still achieve the same results with ease