ComparisonMatchExpression.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. "use strict";
  2. var LeafMatchExpression = require("./LeafMatchExpression"),
  3. Value = require("../pipeline/Value"),
  4. ErrorCodes = require("../errors").ErrorCodes;
  5. /**
  6. * ComparisonMatchExpression
  7. * @class ComparisonMatchExpression
  8. * @namespace mungedb-aggregate.matcher
  9. * @module mungedb-aggregate
  10. * @constructor
  11. */
  12. var ComparisonMatchExpression = module.exports = function ComparisonMatchExpression(type){
  13. base.call(this);
  14. this._matchType = type;
  15. }, klass = ComparisonMatchExpression, base = LeafMatchExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}}); //jshint ignore:line
  16. proto._rhs = undefined;
  17. /**
  18. * Writes a debug string for this object
  19. * @method debugString
  20. * @param level
  21. */
  22. proto.debugString = function debugString(level) {
  23. var retStr = this._debugAddSpace(level) + this.path() + " ";
  24. switch (this._matchType) {
  25. case "LT":
  26. retStr += "$lt";
  27. break;
  28. case "LTE":
  29. retStr += "$lte";
  30. break;
  31. case "EQ":
  32. retStr += "==";
  33. break;
  34. case "GT":
  35. retStr += "$gt";
  36. break;
  37. case "GTE":
  38. retStr += "$gte";
  39. break;
  40. default:
  41. retStr += "Unknown comparison!";
  42. break;
  43. }
  44. retStr += (this._rhs !== undefined ? this._rhs.toString() : "?");
  45. if (this.getTag()) {
  46. retStr += this.getTag().debugString();
  47. }
  48. return retStr + "\n";
  49. };
  50. /**
  51. * checks if this expression is == to the other
  52. * @method equivalent
  53. * @param other
  54. */
  55. proto.equivalent = function equivalent(other) {
  56. if (other._matchType !== this._matchType) return false;
  57. return this.path() === other.path() && Value.compare(this._rhs,other._rhs) === 0;
  58. };
  59. /**
  60. * Return the _rhs property
  61. * @method getData
  62. */
  63. proto.getData = function getData() {
  64. return this._rhs;
  65. };
  66. /**
  67. * Return the _rhs property
  68. * @method getRHS
  69. */
  70. proto.getRHS = function getRHS() {
  71. return this._rhs;
  72. };
  73. /**
  74. * Initialize the necessary items
  75. * @method init
  76. * @param path
  77. * @param type
  78. */
  79. proto.init = function init(path, rhs) {
  80. this._rhs = rhs;
  81. if (Value.getType(rhs) === "Object" && Object.keys(rhs).length === 0) {
  82. return {code:ErrorCodes.BAD_VALUE, description:"need a real operand"};
  83. }
  84. if (rhs === undefined) {
  85. return {code:ErrorCodes.BAD_VALUE, description:"cannot compare to undefined"};
  86. }
  87. switch (this._matchType) {
  88. case "LT":
  89. case "LTE":
  90. case "EQ":
  91. case "GT":
  92. case "GTE":
  93. break;
  94. default:
  95. return {code:ErrorCodes.BAD_VALUE, description:"bad match type for ComparisonMatchExpression"};
  96. }
  97. return this.initPath(path);
  98. };
  99. /**
  100. * Check if the input element matches
  101. * @method matchesSingleElement
  102. * @param e
  103. */
  104. proto.matchesSingleElement = function matchesSingleElement(e) {
  105. if (Value.canonicalize(e) !== Value.canonicalize(this._rhs)) {
  106. // some special cases
  107. // jstNULL and undefined are treated the same
  108. if (Value.canonicalize(e) + Value.canonicalize(this._rhs) === 5) {
  109. return this._matchType === "EQ" || this._matchType === "LTE" || this._matchType === "GTE";
  110. }
  111. var rhsType = Value.getType(this._rhs);
  112. if (rhsType === "MaxKey" || rhsType === "MinKey") {
  113. return this._matchType !== "EQ";
  114. }
  115. return false;
  116. }
  117. var x = Value.compare(e, this._rhs);
  118. switch(this._matchType) {
  119. case "LT":
  120. return x < 0;
  121. case "LTE":
  122. return x <= 0;
  123. case "EQ":
  124. return x === 0;
  125. case "GT":
  126. return x > 0;
  127. case "GTE":
  128. return x >= 0;
  129. default:
  130. throw new Error("Assertion failure: invalid comparison type evaluated; fassert 16828");
  131. }
  132. };