mongo-portable
Version:
Portable Pure JS MongoDB - Based on Monglodb (https://github.com/euforic/monglodb.git) by Christian Sullivan (http://RogueSynaptics.com)
283 lines • 10.5 kB
JavaScript
"use strict";
/**
* @file Cursor.js - based on Monglo#Cursor ({@link https://github.com/Monglo}) by Christian Sullivan <cs@euforic.co> | Copyright (c) 2012
* @version 1.0.0
*
* @author Eduardo Astolfi <eduardo.astolfi91@gmail.com>
* @copyright 2016 Eduardo Astolfi <eduardo.astolfi91@gmail.com>
* @license MIT Licensed
*/
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var jsw_logger_1 = require("jsw-logger");
var _ = require("lodash");
var collection_1 = require("../collection");
var selector_1 = require("../selector");
var stages = {
$project: true,
$match: true,
$redact: false,
$limit: false,
$skip: false,
$unwind: false,
$group: true,
$sample: false,
$sort: true,
$geoNear: false,
$lookup: false,
$out: false,
$indexStats: false
};
var groupOperators = {
$sum: function (documents, newId, newField, value, isCount) {
var e_1, _a, _b;
var newDocs = {};
try {
for (var documents_1 = __values(documents), documents_1_1 = documents_1.next(); !documents_1_1.done; documents_1_1 = documents_1.next()) {
var doc = documents_1_1.value;
var val = value;
if (!isCount) {
val = doc[value.substr(1, value.length)] || 0;
}
if (_.hasIn(doc, newId)) {
var _id = doc[newId];
if (!_.hasIn(newDocs, _id)) {
newDocs[_id] = (_b = {
_id: _id
},
_b[newField] = _.toNumber(val),
_b);
}
else {
newDocs[_id][newField] += _.toNumber(val);
}
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (documents_1_1 && !documents_1_1.done && (_a = documents_1.return)) _a.call(documents_1);
}
finally { if (e_1) throw e_1.error; }
}
return newDocs;
},
$avg: function (documents, newId, newField, value, isCount) {
var e_2, _a, _b, e_3, _c;
var newDocs = {};
try {
for (var documents_2 = __values(documents), documents_2_1 = documents_2.next(); !documents_2_1.done; documents_2_1 = documents_2.next()) {
var doc = documents_2_1.value;
var val = value;
if (!isCount) {
val = doc[value.substr(1, value.length)] || 0;
}
if (_.hasIn(doc, newId) || _.isNull(newId)) {
var _id = doc[newId] || null;
if (!_.hasIn(newDocs, _id)) {
newDocs[_id] = (_b = {
_id: _id
},
_b[newField] = _.toNumber(val),
_b.__COUNT__ = 1,
_b);
}
else {
newDocs[_id][newField] += _.toNumber(val);
newDocs[_id].__COUNT__++;
}
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (documents_2_1 && !documents_2_1.done && (_a = documents_2.return)) _a.call(documents_2);
}
finally { if (e_2) throw e_2.error; }
}
try {
for (var _d = __values(Object.keys(newDocs)), _e = _d.next(); !_e.done; _e = _d.next()) {
var key = _e.value;
newDocs[key][newField] = newDocs[key][newField] / newDocs[key].__COUNT__;
delete newDocs[key].__COUNT__;
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
}
finally { if (e_3) throw e_3.error; }
}
return newDocs;
}
};
var doSingleGroup = function (groupId, groupStage, documents) {
// var operators = {};
var e_4, _a;
var docs = {};
for (var field in groupStage) {
if (field !== "_id") {
// handle group field
// let group_key = key;
var groupField = groupStage[field];
try {
for (var _b = __values(Object.keys(groupField)), _c = _b.next(); !_c.done; _c = _b.next()) {
var key = _c.value;
if (!_.hasIn(groupOperators, key)) {
_this.logger.throw("Unknown accumulator operator \"" + key + "\" for group stage");
}
// loop through all documents
// var newDocs = {};
// for (let i = 0; i < documents.length; i++) {
// let doc = documents[i];
// if (_.hasIn(doc, groupId)) {
// let _id = doc[groupId];
// if (!_.hasIn(newDocs, _id)) {
// newDocs[_id] = {
// _id: _id,
// [newField]: value
// };
// } else {
// newDocs[_id][newField] += value;
// }
// }
// }
// if (!_.hasIn(operators, key)) operators[key] = [];
// operators[key].push({
// newField: field,
// value: groupField[key]
// });
var count = true;
if (_.isString(groupField[key])) {
if (groupField[key].substr(0, 1) !== "$") {
_this.logger.throw("Field names references in a right side assignement must be preceded by '$'");
}
if (!_.isFinite(_.toNumber(groupField[key]))) {
count = false;
}
}
var operator = groupOperators[key];
_.merge(docs, operator(documents, groupId, field, groupField[key], count));
break;
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
}
}
return _.values(docs);
};
var doComplexGroup = function () {
// TODO
};
var doSort = function (documents, sortStage) {
return documents.sort(new selector_1.Selector(sortStage, selector_1.Selector.SORT_SELECTOR));
};
var doMatch = function (documents, matchStage) {
var cursor = new collection_1.Cursor(documents, matchStage);
return cursor.fetch();
};
var doGroup = function (documents, groupStage) {
if (!_.hasIn(groupStage, "_id")) {
_this.logger.throw('The field "_id" is required in the "$group" stage');
}
var newId = groupStage._id;
if (!_.isNull(newId)) {
if (newId.substr(0, 1) !== "$") {
_this.logger.throw("Field names references in a right side assignement must be preceded by '$'");
}
else {
newId = newId.substr(1, newId.length);
}
}
if (_.isPlainObject(newId)) {
// complex_id
// doComplexGroup();
}
else {
// single_id
return doSingleGroup(newId, groupStage, documents);
}
};
var doProject = function (documents, projectStage) {
return collection_1.Cursor.project(documents, projectStage, true);
};
var Aggregation = /** @class */ (function () {
function Aggregation(pipeline) {
this.logger = jsw_logger_1.JSWLogger.instance;
this.pipeline = pipeline;
}
Aggregation.prototype.aggregate = function (collection) {
var e_5, _a, e_6, _b;
var docs = collection.docs;
try {
for (var _c = __values(this.pipeline), _d = _c.next(); !_d.done; _d = _c.next()) {
var stage = _d.value;
try {
for (var _e = __values(Object.keys(stage)), _f = _e.next(); !_f.done; _f = _e.next()) {
var key = _f.value;
switch (key) {
case "$project":
docs = doProject(docs, stage[key]);
break;
case "$match":
docs = doMatch(docs, stage[key]);
break;
case "$group":
docs = doGroup(docs, stage[key]);
break;
case "$sort":
docs = doSort(docs, stage[key]);
break;
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_6) throw e_6.error; }
}
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_5) throw e_5.error; }
}
return docs; // move to cursor
};
Aggregation.prototype.validStage = function (stage) {
if (!_.hasIn(stages, stage)) {
return this.logger.throw("Unknown stage \"" + stage + "\"");
}
if (stages[stage] === false) {
return this.logger.throw("Unsupported stage \"" + stage + "\"");
}
return true;
};
return Aggregation;
}());
exports.Aggregation = Aggregation;
//# sourceMappingURL=Aggregation.js.map