ProjectDocumentSource.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. var DocumentSource = require('./DocumentSource');
  3. /**
  4. * A base class for filter document sources
  5. * @class ProjectDocumentSource
  6. * @namespace mungedb-aggregate.pipeline.documentSources
  7. * @module mungedb-aggregate
  8. * @constructor
  9. * @param [ctx] {ExpressionContext}
  10. **/
  11. var ProjectDocumentSource = module.exports = function ProjectDocumentSource(ctx, exprObj){
  12. if (arguments.length > 2) throw new Error("up to two args expected");
  13. base.call(this, ctx);
  14. this.OE = new ObjectExpression(exprObj);
  15. this._raw = undefined;
  16. this._variables = undefined;
  17. }, klass = ProjectDocumentSource, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  18. // DEPENDENCIES
  19. var Expression = require('../expressions/Expression'),
  20. ObjectExpression = require('../expressions/ObjectExpression'),
  21. Value = require('../Value'),
  22. Variables = require('../expressions/Variables'),
  23. VariablesIdGenerator = require('../expressions/VariablesIdGenerator'),
  24. VariablesParseState = require('../expressions/VariablesParseState');
  25. klass.projectName = "$project";
  26. /**
  27. * Returns the name of project
  28. * @return {string} the name of project
  29. **/
  30. proto.getSourceName = function getSourceName() {
  31. return klass.projectName;
  32. };
  33. proto.getNext = function getNext(callback) {
  34. if (!callback) throw new Error(this.getSourceName() + ' #getNext() requires callback');
  35. var self = this,
  36. out;
  37. this.source.getNext(function(err, input) {
  38. if (err)
  39. return callback(null, err);
  40. if (input === null) {
  41. out = input;
  42. return callback(null, null);
  43. }
  44. /* create the result document */
  45. out = {};
  46. /**
  47. * Use the ExpressionObject to create the base result.
  48. *
  49. * If we're excluding fields at the top level, leave out the _id if
  50. * it is found, because we took care of it above.
  51. **/
  52. self._variables.setRoot(input);
  53. self.OE.addToDocument(out, input, self._variables);
  54. self._variables.clearRoot();
  55. return callback(null, out);
  56. });
  57. return out;
  58. };
  59. /**
  60. * Optimizes the internal ObjectExpression
  61. * @return
  62. **/
  63. proto.optimize = function optimize() {
  64. this.OE = this.OE.optimize();
  65. };
  66. proto.serialize = function serialize(explain) {
  67. var out = {};
  68. out[this.getSourceName()] = this.OE.serialize(explain);
  69. return out;
  70. };
  71. /**
  72. * Builds a new ProjectDocumentSource from an object
  73. * @method createFromJson
  74. * @return {ProjectDocmentSource} a ProjectDocumentSource instance
  75. **/
  76. klass.createFromJson = function(elem, expCtx) {
  77. if (!(elem instanceof Object) || elem.constructor !== Object) throw new Error('Error 15969. Specification must be an object but was ' + typeof elem);
  78. var objectContext = new Expression.ObjectCtx({
  79. isDocumentOk: true,
  80. isTopLevel: true,
  81. isInclusionOk: true
  82. });
  83. var idGenerator = new VariablesIdGenerator(),
  84. vps = new VariablesParseState(idGenerator),
  85. parsed = Expression.parseObject(elem, objectContext, vps),
  86. exprObj = parsed;
  87. if (!exprObj instanceof ObjectExpression) throw new Error("16402, parseObject() returned wrong type of Expression");
  88. //if (!exprObj.getFieldCount() ) throw new Error("uassert 16403: $project requires at least one output field");
  89. var project = new ProjectDocumentSource(expCtx, exprObj);
  90. project._variables = new Variables(idGenerator.getIdCount());
  91. var projectObj = elem;
  92. project.OE = exprObj;
  93. project._raw = elem;
  94. return project;
  95. };
  96. /**
  97. * Adds dependencies to the contained ObjectExpression
  98. * @param {deps} An object that is treated as a set of strings
  99. * @return A string that is part of the GetDepsReturn enum
  100. **/
  101. proto.getDependencies = function getDependencies(deps) {
  102. var path = [];
  103. this.OE.addDependencies(deps, path);
  104. return base.GetDepsReturn.EXHAUSTIVE;
  105. };
  106. /**
  107. * Returns the object that was used to construct the ProjectDocumentSource
  108. * @return {object} the object that was used to construct the ProjectDocumentSource
  109. **/
  110. proto.getRaw = function getRaw() {
  111. return this._raw;
  112. };
  113. proto.toJSON = function toJSON(){
  114. var obj = {};
  115. this.sourceToJson(obj);
  116. return obj;
  117. };