LimitDocumentSource.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. "use strict";
  2. var LimitDocumentSource = module.exports = (function(){
  3. // CONSTRUCTOR
  4. /**
  5. * A document source limiter
  6. *
  7. * @class LimitDocumentSource
  8. * @namespace munge.pipeline.documentsource
  9. * @module munge
  10. * @constructor
  11. * @param {Object} query the match query to use
  12. **/
  13. var klass = module.exports = LimitDocumentSource = function LimitDocumentSource(/* pCtx*/){
  14. if(arguments.length !== 0) throw new Error("zero args expected");
  15. base.call(this);
  16. this.limit = 0;
  17. this.count = 0;
  18. }, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  19. klass.limitName = "$limit";
  20. proto.getSourceName = function getSourceName(){
  21. return klass.limitName;
  22. };
  23. proto.getFactory = function getFactory(){
  24. return klass; // using the ctor rather than a separate .create() method
  25. };
  26. /**
  27. * Coalesce limits together
  28. *
  29. * @param {Object} nextSource the next source
  30. * @return {bool} return whether we can coalese together
  31. **/
  32. proto.coalesce = function coalesce(nextSource) {
  33. var nextLimit = nextSource.constructor === LimitDocumentSource?nextSource:null;
  34. /* if it's not another $limit, we can't coalesce */
  35. if (!nextLimit)
  36. return false;
  37. /* we need to limit by the minimum of the two limits */
  38. if (nextLimit.limit < this.limit)
  39. this.limit = nextLimit.limit;
  40. return true;
  41. };
  42. /**
  43. * Is the source at EOF?
  44. *
  45. * @method eof
  46. **/
  47. proto.eof = function eof() {
  48. return this.pSource.eof() || this.count >= this.limit;
  49. };
  50. /**
  51. * some implementations do the equivalent of verify(!eof()) so check eof() first
  52. *
  53. * @method getCurrent
  54. * @returns {Document} the current Document without advancing
  55. **/
  56. proto.getCurrent = function getCurrent() {
  57. return this.pSource.getCurrent();
  58. };
  59. /**
  60. * Advance the state of the DocumentSource so that it will return the next Document.
  61. * The default implementation returns false, after checking for interrupts.
  62. * Derived classes can call the default implementation in their own implementations in order to check for interrupts.
  63. *
  64. * @method advance
  65. * @returns {Boolean} whether there is another document to fetch, i.e., whether or not getCurrent() will succeed. This default implementation always returns false.
  66. **/
  67. proto.advance = function advance() {
  68. base.prototype.advance.call(this); // check for interrupts
  69. ++this.count;
  70. if (this.count >= this.limit) {
  71. return false;
  72. }
  73. this.pCurrent = this.pSource.getCurrent();
  74. return this.pSource.advance();
  75. };
  76. /**
  77. * Create an object that represents the document source. The object
  78. * will have a single field whose name is the source's name. This
  79. * will be used by the default implementation of addToJsonArray()
  80. * to add this object to a pipeline being represented in JSON.
  81. *
  82. * @method sourceToJson
  83. * @param {Object} builder JSONObjBuilder: a blank object builder to write to
  84. * @param {Boolean} explain create explain output
  85. **/
  86. proto.sourceToJson = function sourceToJson(builder, explain) {
  87. builder.$limit = this.limit;
  88. };
  89. /**
  90. * Creates a new LimitDocumentSource with the input number as the limit
  91. *
  92. * @param {Number} JsonElement this thing is *called* Json, but it expects a number
  93. **/
  94. klass.createFromJson = function createFromJson(JsonElement) {
  95. if (typeof JsonElement !== "number") throw new Error("code 15957; the limit must be specified as a number");
  96. var Limit = proto.getFactory(),
  97. nextLimit = new Limit();
  98. nextLimit.limit = JsonElement;
  99. if ((nextLimit.limit <= 0) || isNaN(nextLimit.limit)) throw new Error("code 15958; the limit must be positive");
  100. return nextLimit;
  101. };
  102. /**
  103. * Reset the document source so that it is ready for a new stream of data.
  104. * Note that this is a deviation from the mongo implementation.
  105. *
  106. * @method reset
  107. **/
  108. proto.reset = function reset(){
  109. this.count = 0;
  110. };
  111. return klass;
  112. })();