PipelineD.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. /**
  3. * Pipeline helper for reading data
  4. * @class PipelineD
  5. * @namespace mungedb-aggregate.pipeline
  6. * @module mungedb-aggregate
  7. * @constructor
  8. **/
  9. var PipelineD = module.exports = function PipelineD(){
  10. if(this.constructor == PipelineD) throw new Error("Never create instances of this! Use the static helpers only.");
  11. }, klass = PipelineD, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  12. // DEPENDENCIES
  13. var DocumentSource = require('./documentSources/DocumentSource'),
  14. CursorDocumentSource = require('./documentSources/CursorDocumentSource'),
  15. Cursor = require('../Cursor');
  16. /**
  17. * Create a Cursor wrapped in a DocumentSourceCursor, which is suitable to be the first source for a pipeline to begin with.
  18. * This source will feed the execution of the pipeline.
  19. *
  20. * //NOTE: DEVIATION FROM THE MONGO: We don't have special optimized cursors; You could support something similar by overriding `Pipeline#run` to call `DocumentSource#coalesce` on the `inputSource` if you really need it.
  21. *
  22. * This method looks for early pipeline stages that can be folded into
  23. * the underlying cursor, and when a cursor can absorb those, they
  24. * are removed from the head of the pipeline. For example, an
  25. * early match can be removed and replaced with a Cursor that will
  26. * do an index scan.
  27. *
  28. * @param pipeline {Pipeline} the logical "this" for this operation
  29. * @param ctx {Object} Context for expressions
  30. * @returns {CursorDocumentSource} the cursor that was created
  31. **/
  32. klass.prepareCursorSource = function prepareCursorSource(pipeline, /*dbName,*/ expCtx){
  33. var sources = pipeline.sourceVector;
  34. //NOTE: SKIPPED: look for initial match
  35. //NOTE: SKIPPED: create a query object
  36. //Look for an initial simple project; we'll avoid constructing Values for fields that won't make it through the projection
  37. var projection = {};
  38. var deps = [];
  39. var status = DocumentSource.GetDepsReturn.SEE_NEXT;
  40. for (var i=0; i < sources.length && status != DocumentSource.GetDepsReturn.EXHAUSTIVE; i++) {
  41. status = sources[i].getDependencies(deps);
  42. }
  43. if (status == DocumentSource.GetDepsReturn.EXHAUSTIVE) {
  44. projection = DocumentSource.depsToProjection(deps);
  45. }
  46. //NOTE: SKIPPED: Look for an initial sort
  47. //NOTE: SKIPPED: Create the sort object
  48. // //get the full "namespace" name
  49. // var fullName = dbName + "." + pipeline.collectionName;
  50. //NOTE: SKIPPED: if(DEV) log messages
  51. //Create the necessary context to use a Cursor
  52. //NOTE: SKIPPED: pSortedCursor bit
  53. //NOTE: SKIPPED: pUnsortedCursor bit
  54. var cursorWithContext = new CursorDocumentSource.CursorWithContext(/*fullName*/);
  55. // Now add the Cursor to cursorWithContext
  56. cursorWithContext._cursor = new Cursor( pipeline.collectionName );
  57. // wrap the cursor with a DocumentSource and return that
  58. var source = new CursorDocumentSource( cursorWithContext, expCtx );
  59. // source.namespace = fullName;
  60. //NOTE: SKIPPED: Note the query and sort
  61. if (Object.keys(projection).length) source.setProjection(projection);
  62. return source;
  63. };