Fix field resolution for ExposedFieldsAggregationContext.

This commit fixes an issue where the context is not relaxed and errors on unknown fields if multiple stages of nesting contexts happen.

Closes #3917
Original pull request: #4328
This commit is contained in:
Christoph Strobl
2023-03-10 12:25:30 +01:00
committed by Mark Paluch
parent 190516f297
commit aecca2998b
2 changed files with 42 additions and 0 deletions

View File

@@ -96,6 +96,25 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
return exposedField;
}
if(rootContext instanceof RelaxedTypeBasedAggregationOperationContext) {
return new DirectFieldReference(new ExposedField(new Field() {
@Override
public String getName() {
return name;
}
@Override
public String getTarget() {
return field != null ? field.getTarget() : name;
}
@Override
public boolean isAliased() {
return true;
}
}, true));
}
throw new IllegalArgumentException(String.format("Invalid reference '%s'", name));
}

View File

@@ -29,6 +29,7 @@ import java.util.Map;
import org.bson.Document;
import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperationUnitTests.BookWithFieldAnnotation;
@@ -629,6 +630,28 @@ public class AggregationUnitTests {
Document target = newAggregation(stage).toDocument("col-1", DEFAULT_CONTEXT);
assertThat(extractPipelineElement(target, 0, "$project")).containsKey("name");
}
@Test // GH-3917
void inheritedFieldsExposingContextShouldNotFailOnUnknownFieldReferenceForRelaxedRootContext() {
List<AggregationOperation> aggregationOperations = new ArrayList<>();
GroupOperation groupOperation = Aggregation.group("_id", "label_name");
aggregationOperations.add(groupOperation);
ProjectionOperation projectionOperation = Aggregation.project("label_name").andExclude("_id");
aggregationOperations.add(projectionOperation);
Sort sort = Sort.by(Sort.Direction.DESC, "serial_number");
SortOperation sortOperation = new SortOperation(sort).and(Sort.Direction.DESC, "label_name");
aggregationOperations.add(sortOperation);
MongoMappingContext mappingContext = new MongoMappingContext();
QueryMapper queryMapper = new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext));
List<Document> documents = newAggregation(City.class, aggregationOperations).toPipeline(new RelaxedTypeBasedAggregationOperationContext(City.class, mappingContext, queryMapper));
assertThat(documents.get(2)).isEqualTo("{ $sort : { 'serial_number' : -1, 'label_name' : -1 } }");
}
private Document extractPipelineElement(Document agg, int index, String operation) {