Add support for $bottomN aggregation operator.
Closes #4139 Original pull request: #4182.
This commit is contained in:
committed by
Mark Paluch
parent
052cfdfd45
commit
59464f3b3c
@@ -38,9 +38,14 @@ public class SelectionOperators {
|
|||||||
super(value);
|
super(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case a limit value ({@literal n}) is present {@literal $bottomN} is used instead of {@literal $bottom}.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected String getMongoMethod() {
|
protected String getMongoMethod() {
|
||||||
return "$bottom";
|
return get("n") == null ? "$bottom" : "$bottomN";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +55,31 @@ public class SelectionOperators {
|
|||||||
return new Bottom(Collections.emptyMap());
|
return new Bottom(Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits the number of returned elements to the given value.
|
||||||
|
*
|
||||||
|
* @param numberOfResults
|
||||||
|
* @return new instance of {@link Bottom}.
|
||||||
|
*/
|
||||||
|
public Bottom limit(int numberOfResults) {
|
||||||
|
return limit((Object) numberOfResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limits the number of returned elements to the value defined by the given {@link AggregationExpression
|
||||||
|
* expression}.
|
||||||
|
*
|
||||||
|
* @param expression must not be {@literal null}.
|
||||||
|
* @return new instance of {@link Bottom}.
|
||||||
|
*/
|
||||||
|
public Bottom limit(AggregationExpression expression) {
|
||||||
|
return limit((Object) expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bottom limit(Object value) {
|
||||||
|
return new Bottom(append("n", value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define result ordering.
|
* Define result ordering.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ public class MethodReferenceNode extends ExpressionNode {
|
|||||||
// OBJECT OPERATORS
|
// OBJECT OPERATORS
|
||||||
map.put("objectToArray", singleArgRef().forOperator("$objectToArray"));
|
map.put("objectToArray", singleArgRef().forOperator("$objectToArray"));
|
||||||
map.put("mergeObjects", arrayArgRef().forOperator("$mergeObjects"));
|
map.put("mergeObjects", arrayArgRef().forOperator("$mergeObjects"));
|
||||||
|
map.put("bottom", mapArgRef().forOperator("$bottom") //
|
||||||
|
.mappingParametersTo("output", "sortBy"));
|
||||||
|
map.put("bottomN", mapArgRef().forOperator("$bottomN") //
|
||||||
|
.mappingParametersTo("n", "output", "sortBy"));
|
||||||
|
|
||||||
// CONVERT OPERATORS
|
// CONVERT OPERATORS
|
||||||
map.put("convert", mapArgRef().forOperator("$convert") //
|
map.put("convert", mapArgRef().forOperator("$convert") //
|
||||||
@@ -226,9 +230,6 @@ public class MethodReferenceNode extends ExpressionNode {
|
|||||||
map.put("toString", singleArgRef().forOperator("$toString"));
|
map.put("toString", singleArgRef().forOperator("$toString"));
|
||||||
map.put("degreesToRadians", singleArgRef().forOperator("$degreesToRadians"));
|
map.put("degreesToRadians", singleArgRef().forOperator("$degreesToRadians"));
|
||||||
|
|
||||||
// SELECT OPERATORS
|
|
||||||
map.put("bottom", mapArgRef().forOperator("$bottom") //
|
|
||||||
.mappingParametersTo("output", "sortBy"));
|
|
||||||
|
|
||||||
FUNCTIONS = Collections.unmodifiableMap(map);
|
FUNCTIONS = Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,24 @@ class SelectionOperatorUnitTests {
|
|||||||
"""));
|
"""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // GH-4139
|
||||||
|
void bottomNRenderedCorrectly() {
|
||||||
|
|
||||||
|
Document document = SelectionOperators.Bottom.bottom().output(Fields.fields("playerId", "score"))
|
||||||
|
.sortBy(Sort.by(Direction.DESC, "score")).limit(3).toDocument(Aggregation.DEFAULT_CONTEXT);
|
||||||
|
|
||||||
|
assertThat(document).isEqualTo(Document.parse("""
|
||||||
|
{
|
||||||
|
$bottomN:
|
||||||
|
{
|
||||||
|
n : 3,
|
||||||
|
output: [ "$playerId", "$score" ],
|
||||||
|
sortBy: { "score": -1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""));
|
||||||
|
}
|
||||||
|
|
||||||
static class Player {
|
static class Player {
|
||||||
|
|
||||||
@Field("player_id") String playerId;
|
@Field("player_id") String playerId;
|
||||||
|
|||||||
@@ -1179,6 +1179,11 @@ public class SpelExpressionTransformerUnitTests {
|
|||||||
assertThat(transform("bottom(new String[]{\"$playerId\", \"$score\" }, { \"score\" : -1 })")).isEqualTo("{ $bottom : { output: [ \"$playerId\", \"$score\" ], sortBy: { \"score\": -1 }}}");
|
assertThat(transform("bottom(new String[]{\"$playerId\", \"$score\" }, { \"score\" : -1 })")).isEqualTo("{ $bottom : { output: [ \"$playerId\", \"$score\" ], sortBy: { \"score\": -1 }}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // GH-4139
|
||||||
|
void shouldRenderBottomN() {
|
||||||
|
assertThat(transform("bottomN(3, new String[]{\"$playerId\", \"$score\" }, { \"score\" : -1 })")).isEqualTo("{ $bottomN : { n : 3, output: [ \"$playerId\", \"$score\" ], sortBy: { \"score\": -1 }}}");
|
||||||
|
}
|
||||||
|
|
||||||
private Document transform(String expression, Object... params) {
|
private Document transform(String expression, Object... params) {
|
||||||
return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
|
return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ At the time of this writing, we provide support for the following Aggregation Op
|
|||||||
| `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue`
|
| `setEquals`, `setIntersection`, `setUnion`, `setDifference`, `setIsSubset`, `anyElementTrue`, `allElementsTrue`
|
||||||
|
|
||||||
| Group/Accumulator Aggregation Operators
|
| Group/Accumulator Aggregation Operators
|
||||||
| `addToSet`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp`
|
| `addToSet`, `bottom`, `bottomN`, `covariancePop`, `covarianceSamp`, `expMovingAvg`, `first`, `last`, `max`, `min`, `avg`, `push`, `sum`, `count` (+++*+++), `stdDevPop`, `stdDevSamp`
|
||||||
|
|
||||||
| Arithmetic Aggregation Operators
|
| Arithmetic Aggregation Operators
|
||||||
| `abs`, `acos`, `acosh`, `add` (+++*+++ via `plus`), `asin`, `asin`, `atan`, `atan2`, `atanh`, `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc`
|
| `abs`, `acos`, `acosh`, `add` (+++*+++ via `plus`), `asin`, `asin`, `atan`, `atan2`, `atanh`, `ceil`, `cos`, `cosh`, `derivative`, `divide`, `exp`, `floor`, `integral`, `ln`, `log`, `log10`, `mod`, `multiply`, `pow`, `round`, `sqrt`, `subtract` (+++*+++ via `minus`), `sin`, `sinh`, `tan`, `tanh`, `trunc`
|
||||||
@@ -120,9 +120,6 @@ At the time of this writing, we provide support for the following Aggregation Op
|
|||||||
| Script Aggregation Operators
|
| Script Aggregation Operators
|
||||||
| `function`, `accumulator`
|
| `function`, `accumulator`
|
||||||
|
|
||||||
| Selection Aggregation Operators
|
|
||||||
| `bottom`
|
|
||||||
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
+++*+++ The operation is mapped or added by Spring Data MongoDB.
|
+++*+++ The operation is mapped or added by Spring Data MongoDB.
|
||||||
|
|||||||
Reference in New Issue
Block a user