Skip to content

Commit 0db4716

Browse files
christophstroblmp911de
authored andcommitted
Add support for $sin and $sinh aggregation operators.
Closes: #3728 Original pull request: #3755.
1 parent ec16b87 commit 0db4716

File tree

4 files changed

+286
-0
lines changed

4 files changed

+286
-0
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperators.java

+246
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.data.mongodb.core.aggregation.SetWindowFieldsOperation.WindowUnits;
3232
import org.springframework.lang.Nullable;
3333
import org.springframework.util.Assert;
34+
import org.springframework.util.ObjectUtils;
3435
import org.springframework.util.StringUtils;
3536

3637
/**
@@ -676,6 +677,48 @@ public Round roundToPlace(int place) {
676677
return round().place(place);
677678
}
678679

680+
/**
681+
* Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}.
682+
*
683+
* @return new instance of {@link Sin}.
684+
* @since 3.3
685+
*/
686+
public Sin sin() {
687+
return sin(AngularDimension.RADIANS);
688+
}
689+
690+
/**
691+
* Creates new {@link AggregationExpression} that calculates the sine of a numeric value in the given {@link AngularDimension unit}.
692+
*
693+
* @param unit the unit of measure.
694+
* @return new instance of {@link Sin}.
695+
* @since 3.3
696+
*/
697+
public Sin sin(AngularDimension unit) {
698+
return usesFieldRef() ? Sin.sinOf(fieldReference, unit) : Sin.sinOf(expression, unit);
699+
}
700+
701+
/**
702+
* Creates new {@link AggregationExpression} that calculates the sine of a numeric value given in {@link AngularDimension#RADIANS radians}.
703+
*
704+
* @return new instance of {@link Sin}.
705+
* @since 3.3
706+
*/
707+
public Sinh sinh() {
708+
return sinh(AngularDimension.RADIANS);
709+
}
710+
711+
/**
712+
* Creates new {@link AggregationExpression} that calculates the sine of a numeric value.
713+
*
714+
* @param unit the unit of measure.
715+
* @return new instance of {@link Sin}.
716+
* @since 3.3
717+
*/
718+
public Sinh sinh(AngularDimension unit) {
719+
return usesFieldRef() ? Sinh.sinhOf(fieldReference, unit) : Sinh.sinhOf(expression, unit);
720+
}
721+
679722
private boolean usesFieldRef() {
680723
return fieldReference != null;
681724
}
@@ -1907,4 +1950,207 @@ protected String getMongoMethod() {
19071950
return "$integral";
19081951
}
19091952
}
1953+
1954+
/**
1955+
* The unit of measure for computations that operate upon angles.
1956+
*
1957+
* @author Christoph Strobl
1958+
* @since 3.3
1959+
*/
1960+
public enum AngularDimension {
1961+
RADIANS, DEGREES
1962+
}
1963+
1964+
/**
1965+
* An {@link AggregationExpression expression} that calculates the sine of a value that is measured in radians.
1966+
*
1967+
* @author Christoph Strobl
1968+
* @since 3.3
1969+
*/
1970+
public static class Sin extends AbstractAggregationExpression {
1971+
1972+
private Sin(Object value) {
1973+
super(value);
1974+
}
1975+
1976+
/**
1977+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in
1978+
* {@link AngularDimension#RADIANS radians}.
1979+
* <p />
1980+
* Use {@code sinhOf("angle", DEGREES)} as shortcut for <pre>{ $sinh : { $degreesToRadians : "$angle" } }</pre>.
1981+
*
1982+
* @param fieldReference the name of the {@link Field field} that resolves to a numeric value.
1983+
* @return new instance of {@link Sin}.
1984+
*/
1985+
public static Sin sinOf(String fieldReference) {
1986+
return sinOf(fieldReference, AngularDimension.RADIANS);
1987+
}
1988+
1989+
/**
1990+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given
1991+
* {@link AngularDimension unit}.
1992+
*
1993+
* @param fieldReference the name of the {@link Field field} that resolves to a numeric value.
1994+
* @param unit the unit of measure used by the value of the given field.
1995+
* @return new instance of {@link Sin}.
1996+
*/
1997+
public static Sin sinOf(String fieldReference, AngularDimension unit) {
1998+
return sin(Fields.field(fieldReference), unit);
1999+
}
2000+
2001+
/**
2002+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in
2003+
* {@link AngularDimension#RADIANS}.
2004+
*
2005+
* @param expression the {@link AggregationExpression expression} that resolves to a numeric value.
2006+
* @return new instance of {@link Sin}.
2007+
*/
2008+
public static Sin sinOf(AggregationExpression expression) {
2009+
return sinOf(expression, AngularDimension.RADIANS);
2010+
}
2011+
2012+
/**
2013+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given
2014+
* {@link AngularDimension unit}.
2015+
*
2016+
* @param expression the {@link AggregationExpression expression} that resolves to a numeric value.
2017+
* @param unit the unit of measure used by the value of the given field.
2018+
* @return new instance of {@link Sin}.
2019+
*/
2020+
public static Sin sinOf(AggregationExpression expression, AngularDimension unit) {
2021+
return sin(expression, unit);
2022+
}
2023+
2024+
/**
2025+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in
2026+
* {@link AngularDimension#RADIANS}.
2027+
*
2028+
* @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
2029+
* numeric value
2030+
* @return new instance of {@link Sin}.
2031+
*/
2032+
public static Sin sin(Object value) {
2033+
return sin(value, AngularDimension.RADIANS);
2034+
}
2035+
2036+
/**
2037+
* Creates a new {@link AggregationExpression} that calculates the sine of a value that is measured in the given
2038+
* {@link AngularDimension unit}.
2039+
*
2040+
* @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
2041+
* numeric value.
2042+
* @param unit the unit of measure used by the value of the given field.
2043+
* @return new instance of {@link Sin}.
2044+
*/
2045+
public static Sin sin(Object value, AngularDimension unit) {
2046+
2047+
if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) {
2048+
return new Sin(ConvertOperators.DegreesToRadians.degreesToRadians(value));
2049+
}
2050+
return new Sin(value);
2051+
}
2052+
2053+
@Override
2054+
protected String getMongoMethod() {
2055+
return "$sin";
2056+
}
2057+
}
2058+
2059+
/**
2060+
* An {@link AggregationExpression expression} that calculates the hyperbolic sine of a value that is measured in
2061+
* {@link AngularDimension#RADIANS}.
2062+
*
2063+
* @author Christoph Strobl
2064+
* @since 3.3
2065+
*/
2066+
public static class Sinh extends AbstractAggregationExpression {
2067+
2068+
private Sinh(Object value) {
2069+
super(value);
2070+
}
2071+
2072+
/**
2073+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2074+
* {@link AngularDimension#RADIANS}.
2075+
*
2076+
* @param fieldReference the name of the {@link Field field} that resolves to a numeric value.
2077+
* @return new instance of {@link Sin}.
2078+
*/
2079+
public static Sinh sinhOf(String fieldReference) {
2080+
return sinhOf(fieldReference, AngularDimension.RADIANS);
2081+
}
2082+
2083+
/**
2084+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2085+
* the given {@link AngularDimension unit}.
2086+
* <p />
2087+
* Use {@code sinhOf("angle", DEGREES)} as shortcut for <pre>{ $sinh : { $degreesToRadians : "$angle" } }</pre>.
2088+
*
2089+
* @param fieldReference the name of the {@link Field field} that resolves to a numeric value.
2090+
* @param unit the unit of measure used by the value of the given field.
2091+
* @return new instance of {@link Sin}.
2092+
*/
2093+
public static Sinh sinhOf(String fieldReference, AngularDimension unit) {
2094+
return sinh(Fields.field(fieldReference), unit);
2095+
}
2096+
2097+
/**
2098+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2099+
* {@link AngularDimension#RADIANS}.
2100+
* <p />
2101+
* Use {@code sinhOf("angle", DEGREES)} as shortcut for eg. {@code sinhOf(ConvertOperators.valueOf("angle").degreesToRadians())}.
2102+
*
2103+
* @param expression the {@link AggregationExpression expression} that resolves to a numeric value.
2104+
* @return new instance of {@link Sin}.
2105+
*/
2106+
public static Sinh sinhOf(AggregationExpression expression) {
2107+
return sinhOf(expression, AngularDimension.RADIANS);
2108+
}
2109+
2110+
/**
2111+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2112+
* the given {@link AngularDimension unit}.
2113+
*
2114+
* @param expression the {@link AggregationExpression expression} that resolves to a numeric value.
2115+
* @param unit the unit of measure used by the value of the given field.
2116+
* @return new instance of {@link Sin}.
2117+
*/
2118+
public static Sinh sinhOf(AggregationExpression expression, AngularDimension unit) {
2119+
return sinh(expression, unit);
2120+
}
2121+
2122+
/**
2123+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2124+
* {@link AngularDimension#RADIANS}.
2125+
*
2126+
* @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
2127+
* numeric value.
2128+
* @return new instance of {@link Sin}.
2129+
*/
2130+
public static Sinh sinh(Object value) {
2131+
return sinh(value, AngularDimension.RADIANS);
2132+
}
2133+
2134+
/**
2135+
* Creates a new {@link AggregationExpression} that calculates the hyperbolic sine of a value that is measured in
2136+
* the given {@link AngularDimension unit}.
2137+
*
2138+
* @param value anything ({@link Field field}, {@link AggregationExpression expression}, ...) that resolves to a
2139+
* numeric value
2140+
* @param unit the unit of measure used by the value of the given field.
2141+
* @return new instance of {@link Sin}.
2142+
*/
2143+
public static Sinh sinh(Object value, AngularDimension unit) {
2144+
2145+
if (ObjectUtils.nullSafeEquals(AngularDimension.DEGREES, unit)) {
2146+
return new Sinh(ConvertOperators.DegreesToRadians.degreesToRadians(value));
2147+
}
2148+
return new Sinh(value);
2149+
}
2150+
2151+
@Override
2152+
protected String getMongoMethod() {
2153+
return "$sinh";
2154+
}
2155+
}
19102156
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/spel/MethodReferenceNode.java

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ public class MethodReferenceNode extends ExpressionNode {
9393
map.put("round", arrayArgRef().forOperator("$round"));
9494
map.put("derivative", mapArgRef().forOperator("$derivative").mappingParametersTo("input", "unit"));
9595
map.put("integral", mapArgRef().forOperator("$integral").mappingParametersTo("input", "unit"));
96+
map.put("sin", singleArgRef().forOperator("$sin"));
97+
map.put("sinh", singleArgRef().forOperator("$sinh"));
9698

9799
// STRING OPERATORS
98100
map.put("concat", arrayArgRef().forOperator("$concat"));

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/ArithmeticOperatorsUnitTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,32 @@ void rendersIntegralWithUnit() {
8181
.toDocument(Aggregation.DEFAULT_CONTEXT))
8282
.isEqualTo("{ $integral : { input : \"$kilowatts\", unit : \"hour\" } }");
8383
}
84+
85+
@Test // GH-3728
86+
void rendersSin() {
87+
88+
assertThat(valueOf("angle").sin().toDocument(Aggregation.DEFAULT_CONTEXT))
89+
.isEqualTo(Document.parse("{ $sin : \"$angle\" }"));
90+
}
91+
92+
@Test // GH-3728
93+
void rendersSinWithValueInDegrees() {
94+
95+
assertThat(valueOf("angle").sin(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT))
96+
.isEqualTo(Document.parse("{ $sin : { $degreesToRadians : \"$angle\" } }"));
97+
}
98+
99+
@Test // GH-3728
100+
void rendersSinh() {
101+
102+
assertThat(valueOf("angle").sinh().toDocument(Aggregation.DEFAULT_CONTEXT))
103+
.isEqualTo(Document.parse("{ $sinh : \"$angle\" }"));
104+
}
105+
106+
@Test // GH-3728
107+
void rendersSinhWithValueInDegrees() {
108+
109+
assertThat(valueOf("angle").sinh(AngularDimension.DEGREES).toDocument(Aggregation.DEFAULT_CONTEXT))
110+
.isEqualTo(Document.parse("{ $sinh : { $degreesToRadians : \"$angle\" } }"));
111+
}
84112
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,16 @@ void shouldRenderIntegralWithUnit() {
10041004
.isEqualTo(Document.parse("{ \"$integral\" : { \"input\" : \"$field\", \"unit\" : \"hour\" }}"));
10051005
}
10061006

1007+
@Test // GH-3728
1008+
void shouldRenderSin() {
1009+
assertThat(transform("sin(angle)")).isEqualTo(Document.parse("{ \"$sin\" : \"$angle\"}"));
1010+
}
1011+
1012+
@Test // GH-3728
1013+
void shouldRenderSinh() {
1014+
assertThat(transform("sinh(angle)")).isEqualTo(Document.parse("{ \"$sinh\" : \"$angle\"}"));
1015+
}
1016+
10071017
private Object transform(String expression, Object... params) {
10081018
Object result = transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
10091019
return result == null ? null : (!(result instanceof org.bson.Document) ? result.toString() : result);

0 commit comments

Comments
 (0)