Add support for $lastN aggregation operator.
Closes #4139 Original pull request: #4182.
This commit is contained in:
committed by
Mark Paluch
parent
5525a4fbf9
commit
cdfe2a0b59
@@ -216,4 +216,98 @@ public class SelectionOperators {
|
||||
return "$firstN";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AbstractAggregationExpression} to return the {@literal $lastN} elements.
|
||||
*/
|
||||
public static class Last extends AbstractAggregationExpression {
|
||||
|
||||
protected Last(Object value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new instance of {@link Last}.
|
||||
*/
|
||||
public static Last last() {
|
||||
return new Last(Collections.emptyMap()).limit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new instance of {@link Last}.
|
||||
*/
|
||||
public static Last last(int numberOfResults) {
|
||||
return new Last(Collections.emptyMap()).limit(numberOfResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits the number of returned elements to the given value.
|
||||
*
|
||||
* @param numberOfResults
|
||||
* @return new instance of {@link Bottom}.
|
||||
*/
|
||||
public Last 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 Last limit(AggregationExpression expression) {
|
||||
return limit((Object) expression);
|
||||
}
|
||||
|
||||
private Last limit(Object value) {
|
||||
return new Last(append("n", value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the field to serve as source.
|
||||
*
|
||||
* @param fieldName must not be {@literal null}.
|
||||
* @return new instance of {@link Bottom}.
|
||||
*/
|
||||
public Last of(String fieldName) {
|
||||
return input(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the expression building the value to serve as source.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Bottom}.
|
||||
*/
|
||||
public Last of(AggregationExpression expression) {
|
||||
return input(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the field to serve as source.
|
||||
*
|
||||
* @param fieldName must not be {@literal null}.
|
||||
* @return new instance of {@link Bottom}.
|
||||
*/
|
||||
public Last input(String fieldName) {
|
||||
return new Last(append("input", Fields.field(fieldName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the expression building the value to serve as source.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Bottom}.
|
||||
*/
|
||||
public Last input(AggregationExpression expression) {
|
||||
return new Last(append("input", expression));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMongoMethod() {
|
||||
return "$lastN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,8 @@ public class MethodReferenceNode extends ExpressionNode {
|
||||
.mappingParametersTo("n", "output", "sortBy"));
|
||||
map.put("firstN", mapArgRef().forOperator("$firstN") //
|
||||
.mappingParametersTo("n", "input"));
|
||||
map.put("lastN", mapArgRef().forOperator("$lastN") //
|
||||
.mappingParametersTo("n", "input"));
|
||||
|
||||
// CONVERT OPERATORS
|
||||
map.put("convert", mapArgRef().forOperator("$convert") //
|
||||
|
||||
@@ -110,6 +110,27 @@ class SelectionOperatorUnitTests {
|
||||
"""));
|
||||
}
|
||||
|
||||
@Test // GH-4139
|
||||
void lastNMapsFieldNamesCorrectly() {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
RelaxedTypeBasedAggregationOperationContext aggregationContext = new RelaxedTypeBasedAggregationOperationContext(
|
||||
Player.class, mappingContext,
|
||||
new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)));
|
||||
|
||||
Document document = SelectionOperators.Last.last(3).of("score").toDocument(aggregationContext);
|
||||
|
||||
assertThat(document).isEqualTo(Document.parse("""
|
||||
{
|
||||
$lastN:
|
||||
{
|
||||
n: 3,
|
||||
input: "$s_cor_e"
|
||||
}
|
||||
}
|
||||
"""));
|
||||
}
|
||||
|
||||
static class Player {
|
||||
|
||||
@Field("player_id") String playerId;
|
||||
|
||||
@@ -1189,6 +1189,11 @@ public class SpelExpressionTransformerUnitTests {
|
||||
assertThat(transform("firstN(3, \"$score\")")).isEqualTo("{ $firstN : { n : 3, input : \"$score\" }}");
|
||||
}
|
||||
|
||||
@Test // GH-4139
|
||||
void shouldRenderLastN() {
|
||||
assertThat(transform("lastN(3, \"$score\")")).isEqualTo("{ $lastN : { n : 3, input : \"$score\" }}");
|
||||
}
|
||||
|
||||
private Document transform(String expression, Object... params) {
|
||||
return (Document) transformer.transform(expression, Aggregation.DEFAULT_CONTEXT, params);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user