CompareExpression.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. "use strict";
  2. /**
  3. * Generic comparison expression that gets used for $eq, $ne, $lt, $lte, $gt, $gte, and $cmp.
  4. * @class CompareExpression
  5. * @namespace mungedb-aggregate.pipeline.expressions
  6. * @module mungedb-aggregate
  7. * @constructor
  8. **/
  9. var CompareExpression = module.exports = function CompareExpression(cmpOp) {
  10. if (arguments.length !== 1) throw new Error("args expected: cmpOp");
  11. this.cmpOp = cmpOp;
  12. base.call(this);
  13. }, klass = CompareExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  14. // DEPENDENCIES
  15. var Value = require("../Value"),
  16. Expression = require("./Expression"),
  17. ConstantExpression = require("./ConstantExpression"),
  18. FieldPathExpression = require("./FieldPathExpression"),
  19. FieldRangeExpression = require("./FieldRangeExpression");
  20. // NESTED CLASSES
  21. /**
  22. * Lookup table for truth value returns
  23. *
  24. * @param truthValues truth value for -1, 0, 1
  25. * @param reverse reverse comparison operator
  26. * @param name string name
  27. **/
  28. var CmpLookup = (function(){ // emulating a struct
  29. // CONSTRUCTOR
  30. var klass = function CmpLookup(truthValues, reverse, name) {
  31. if(arguments.length !== 3) throw new Error("args expected: truthValues, reverse, name");
  32. this.truthValues = truthValues;
  33. this.reverse = reverse;
  34. this.name = name;
  35. }, base = Object, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  36. return klass;
  37. })();
  38. // verify we need this below
  39. // PRIVATE STATIC MEMBERS
  40. /**
  41. * a table of cmp type lookups to truth values
  42. * @private
  43. **/
  44. var cmpLookupMap = [ //NOTE: converted from this Array to a Dict/Object below using CmpLookup#name as the key
  45. // -1 0 1 reverse name (taking advantage of the fact that our 'enums' are strings below)
  46. new CmpLookup([false, true, false], CompareExpression.EQ, CompareExpression.EQ),
  47. new CmpLookup([true, false, true], CompareExpression.NE, CompareExpression.NE),
  48. new CmpLookup([false, false, true], CompareExpression, CompareExpression.GT),
  49. new CmpLookup([false, true, true], CompareExpression.LTE, CompareExpression.GTE),
  50. new CmpLookup([true, false, false], CompareExpression.GT, CompareExpression.LT),
  51. new CmpLookup([true, true, false], CompareExpression.GTE, CompareExpression.LTE),
  52. new CmpLookup([false, false, false], CompareExpression.CMP, CompareExpression.CMP)
  53. ].reduce(function(r,o){r[o.name]=o;return r;},{});
  54. // PROTOTYPE MEMBERS
  55. proto.evaluateInternal = function evaluateInternal(doc) {
  56. this.checkArgCount(2);
  57. var left = this.operands[0].evaluateInternal(doc),
  58. right = this.operands[1].evaluateInternal(doc),
  59. cmp = Expression.signum(Value.compare(left, right));
  60. if (this.cmpOp == Expression.CmpOp.CMP) return cmp;
  61. return cmpLookupMap[this.cmpOp].truthValues[cmp + 1] || false;
  62. };
  63. klass.EQ = "$eq";
  64. klass.NE = "$ne";
  65. klass.GT = "$gt";
  66. klass.GTE = "$gte";
  67. klass.LT = "$lt";
  68. klass.LTE = "$lte";
  69. klass.CMP = "$cmp";
  70. proto.getOpName = function getOpName(){
  71. return this.cmpOp;
  72. };