docs: function (a, op, negate) {
              !Dataset && (Dataset = require("./dataset"));
              op = op || "AND", negate = negate || false;
              var pairArr = [];
              var isArr = isArray(a) && Expression.isConditionSpecifier(a);
              if (isHash(a)) {
                  pairArr.push(this.__filterObject(a, null, op));
              } else {
                  for (var k in a) {
                      var v = isArr ? a[k][1] : a[k], ret;
                      k = isArr ? a[k][0] : k;
                      if (isArray(v) || isInstanceOf(v, Dataset)) {
                          k = isArray(k) ? k.map(sql.stringToIdentifier) : sql.stringToIdentifier(k);
                          ret = new BooleanExpression("IN", k, v);
                      } else if (isInstanceOf(v, NegativeBooleanConstant)) {
                          ret = new BooleanExpression("ISNOT", k, v.constant);
                      } else if (isInstanceOf(v, BooleanConstant)) {
                          ret = new BooleanExpression("IS", k, v.constant);
                      } else if (isNull(v) || isBoolean(v)) {
                          ret = new BooleanExpression("IS", k, v);
                      } else if (isHash(v)) {
                          ret = BooleanExpression.__filterObject(v, k, op);
                      } else if (isRegExp(v)) {
                          ret = StringExpression.like(sql.stringToIdentifier(k), v);
                      } else {
                          ret = new BooleanExpression("EQ", sql.stringToIdentifier(k), v);
                      }
                      negate && (ret = BooleanExpression.invert(ret));
                      pairArr.push(ret);
                  }
              }
              //if We just have one then return the first otherwise create a new Boolean expression
              return pairArr.length === 1 ? pairArr[0] : BooleanExpression.fromArgs([op].concat(pairArr));
          }