From ba73a618c3868d7861455d80d7ae37f797822cd8 Mon Sep 17 00:00:00 2001 From: Sebastien Gerard Date: Wed, 16 Nov 2016 15:06:44 +0100 Subject: [PATCH] DATAMONGO-1530: support missing pipeline operators available in Mongo 3.2 --- .../core/spel/MethodReferenceNode.java | 78 ++++++++++++++++--- .../data/mongodb/core/spel/OperatorNode.java | 18 ++--- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java index a32c49c3c1..f94c5ae019 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java @@ -15,32 +15,87 @@ */ package org.springframework.data.mongodb.core.spel; +import org.springframework.expression.spel.ExpressionState; +import org.springframework.expression.spel.ast.MethodReference; + import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.springframework.expression.spel.ExpressionState; -import org.springframework.expression.spel.ast.MethodReference; - /** * An {@link ExpressionNode} representing a method reference. - * + * * @author Oliver Gierke * @author Thomas Darimont + * @author Sebastien Gerard */ public class MethodReferenceNode extends ExpressionNode { private static final Map FUNCTIONS; static { - Map map = new HashMap(); + map.put("and", "$and"); // Returns true only when all its expressions evaluate to true. + map.put("or", "$or"); // Returns true when any of its expressions evaluates to true. + map.put("not", "$not"); // Returns the boolean value that is the opposite of its argument expression. + + map.put("setEquals", "$setEquals"); // Returns true if the input sets have the same distinct elements. + map.put("setIntersection", "$setIntersection"); // Returns a set with elements that appear in all of the input sets. + map.put("setUnion", "$setUnion"); // Returns a set with elements that appear in any of the input sets. + map.put("setDifference", "$setDifference"); // Returns a set with elements that appear in the 1st set but not in the 2nd. + map.put("setIsSubset", "$setIsSubset"); // Returns true if all elements of the 1st set appear in the 2nd set. + map.put("anyElementTrue", "$anyElementTrue"); // Returns whether any elements of a set evaluate to true. + map.put("allElementsTrue", "$allElementsTrue"); // Returns whether no element of a set evaluates to false. + + map.put("cmp", "$cmp"); // Returns: 0 if the two values are equivalent, 1 if the first value is greater than the + // second, and -1 if the first value is less than the second. + map.put("eq", "$eq"); // Returns true if the values are equivalent. + map.put("gt", "$gt"); // Returns true if the first value is greater than the second. + map.put("gte", "$gte"); // Returns true if the first value is greater than or equal to the second. + map.put("lt", "$lt"); // Returns true if the first value is less than the second. + map.put("lte", "$lte"); // Returns true if the first value is less than or equal to the second. + map.put("ne", "$ne"); // Returns true if the values are not equivalent. + + map.put("abs", "$abs"); // Returns the absolute value of a number.; + map.put("add", "$add"); // Adds numbers to return the sum, or adds numbers and a date to return a new date. + map.put("ceil", "$ceil"); // Returns the smallest integer greater than or equal to the specified number. + map.put("divide", "$divide"); // Returns the result of dividing the first number by the second. + map.put("exp", "$exp"); // Raises e to the specified exponent. + map.put("floor", "$floor"); // Returns the largest integer less than or equal to the specified number. + map.put("ln", "$ln"); // Calculates the natural log of a number. + map.put("log", "$log"); // Calculates the log of a number in the specified base. + map.put("log10", "$log10"); // Calculates the log base 10 of a number. + map.put("mod", "$mod"); // Returns the remainder of the first number divided by the second. + map.put("multiply", "$multiply"); // Multiplies numbers to return the product. + map.put("pow", "$pow"); // Raises a number to the specified exponent. + map.put("sqrt", "$sqrt"); // Calculates the square root. + map.put("subtract", "$subtract"); // Returns the result of subtracting the second value from the first. If the + // two values are numbers, return the difference. If the two values are dates, return the difference in milliseconds. + map.put("trunc", "$trunc"); // Truncates a number to its integer. + map.put("concat", "$concat"); // Concatenates two strings. - map.put("strcasecmp", "$strcasecmp"); // Compares two strings and returns an integer that reflects the comparison. map.put("substr", "$substr"); // Takes a string and returns portion of that string. map.put("toLower", "$toLower"); // Converts a string to lowercase. map.put("toUpper", "$toUpper"); // Converts a string to uppercase. + map.put("strcasecmp", "$strcasecmp"); // Compares two strings and returns an integer that reflects the comparison. + + map.put("meta", "$meta"); // Access text search metadata. + + map.put("arrayElemAt", "$arrayElemAt"); // Returns the element at the specified array index. + map.put("concatArrays", "$concatArrays"); // Concatenates arrays to return the concatenated array. + map.put("filter", "$filter"); // Selects a subset of the array to return an array with only the elements that + // match the filter condition. + map.put("isArray", "$isArray"); // Determines if the operand is an array. Returns a boolean. + map.put("size", "$size"); // Returns the number of elements in the array. + map.put("slice", "$slice"); // Returns a subset of an array. + + map.put("map", "$map"); // Applies a subexpression to each element of an array and returns the array of + // resulting values in order. + map.put("let", "$let"); // Defines variables for use within the scope of a subexpression and returns the result + // of the subexpression. + + map.put("literal", "$literal"); // Return a value without parsing. map.put("dayOfYear", "$dayOfYear"); // Converts a date to a number between 1 and 366. map.put("dayOfMonth", "$dayOfMonth"); // Converts a date to a number between 1 and 31. @@ -52,7 +107,13 @@ public class MethodReferenceNode extends ExpressionNode { map.put("minute", "$minute"); // Converts a date into a number between 0 and 59. map.put("second", "$second"); // Converts a date into a number between 0 and 59. May be 60 to account for leap // seconds. - map.put("millisecond", "$millisecond"); // Returns the millisecond portion of a date as an integer between 0 and + map.put("millisecond", "$millisecond"); // Returns the millisecond portion of a date as an integer between 0 and 999. + map.put("dateToString", "$dateToString"); // Returns the date as a formatted string. + + map.put("cond", "$cond"); // A ternary operator that evaluates one expression, and depending on the result, + // returns the value of one of the other two expressions. + map.put("ifNull", "$ifNull"); // Returns either the non-null result of the first expression or the result of the + // second expression if the first expression results in a null result. FUNCTIONS = Collections.unmodifiableMap(map); } @@ -63,11 +124,8 @@ public class MethodReferenceNode extends ExpressionNode { /** * Returns the name of the method. - * - * @return */ public String getMethodName() { - String name = getName(); String methodName = name.substring(0, name.indexOf('(')); return FUNCTIONS.get(methodName); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java index 55a11bd7ec..23475d9584 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/OperatorNode.java @@ -29,7 +29,7 @@ /** * An {@link ExpressionNode} representing an operator. - * + * * @author Oliver Gierke * @author Thomas Darimont */ @@ -47,6 +47,10 @@ public class OperatorNode extends ExpressionNode { map.put("/", "$divide"); map.put("%", "$mod"); + map.put("and", "and"); + map.put("or", "or"); + map.put("!", "not"); + OPERATORS = Collections.unmodifiableMap(map); } @@ -54,7 +58,7 @@ public class OperatorNode extends ExpressionNode { /** * Creates a new {@link OperatorNode} from the given {@link Operator} and {@link ExpressionState}. - * + * * @param node must not be {@literal null}. * @param state must not be {@literal null}. */ @@ -75,8 +79,6 @@ public boolean isMathematicalOperation() { /** * Returns whether the operator is unary. - * - * @return */ public boolean isUnaryOperator() { return operator.getRightOperand() == null; @@ -84,8 +86,6 @@ public boolean isUnaryOperator() { /** * Returns the Mongo expression of the operator. - * - * @return */ public String getMongoOperator() { return OPERATORS.get(operator.getOperatorName()); @@ -93,8 +93,6 @@ public String getMongoOperator() { /** * Returns whether the operator is a unary minus, e.g. -1. - * - * @return */ public boolean isUnaryMinus() { return isUnaryOperator() && operator instanceof OpMinus; @@ -102,8 +100,6 @@ public boolean isUnaryMinus() { /** * Returns the left operand as {@link ExpressionNode}. - * - * @return */ public ExpressionNode getLeft() { return from(operator.getLeftOperand()); @@ -111,8 +107,6 @@ public ExpressionNode getLeft() { /** * Returns the right operand as {@link ExpressionNode}. - * - * @return */ public ExpressionNode getRight() { return from(operator.getRightOperand());