Skip to content

Commit 9920777

Browse files
sxhinzvcchristophstrobl
authored andcommitted
Fix mapping custom field names in downstream stages in TypedAggregation pipelines.
Use the root AggregationOperationContext in nested ExposedFieldsAggregationOperationContext to properly apply mapping for domain properties that use @field. Closes #4443 Original Pull Request: #4459
1 parent fc26641 commit 9920777

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ public Document getMappedObject(Document document, @Nullable Class<?> type) {
6060
return rootContext.getMappedObject(document, type);
6161
}
6262

63+
@Override
64+
public Document getMappedObject(Document document) {
65+
return rootContext.getMappedObject(document);
66+
}
67+
6368
@Override
6469
public FieldReference getReference(Field field) {
6570

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

+21-2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
* @author Maninder Singh
9191
* @author Sergey Shcherbakov
9292
* @author Minsu Kim
93+
* @author Julia Lee
9394
*/
9495
@ExtendWith(MongoTemplateExtension.class)
9596
public class AggregationTests {
@@ -118,7 +119,7 @@ private void cleanDb() {
118119

119120
mongoTemplate.flush(Product.class, UserWithLikes.class, DATAMONGO753.class, Data.class, DATAMONGO788.class,
120121
User.class, Person.class, Reservation.class, Venue.class, MeterData.class, LineItem.class, InventoryItem.class,
121-
Sales.class, Sales2.class, Employee.class, Art.class, Venue.class);
122+
Sales.class, Sales2.class, Employee.class, Art.class, Venue.class, Item.class);
122123

123124
mongoTemplate.dropCollection(INPUT_COLLECTION);
124125
mongoTemplate.dropCollection("personQueryTemp");
@@ -1952,6 +1953,23 @@ void considersMongoIdWithinTypedCollections() {
19521953
assertThat(aggregate.getMappedResults()).contains(widget);
19531954
}
19541955

1956+
@Test // GH-4443
1957+
void shouldHonorFieldAliasesForFieldReferencesUsingFieldExposingOperation() {
1958+
1959+
Item item1 = Item.builder().itemId("1").tags(Arrays.asList("a", "b")).build();
1960+
Item item2 = Item.builder().itemId("1").tags(Arrays.asList("a", "c")).build();
1961+
mongoTemplate.insert(Arrays.asList(item1, item2), Item.class);
1962+
1963+
TypedAggregation<Item> aggregation = newAggregation(Item.class,
1964+
match(where("itemId").is("1")),
1965+
unwind("tags"),
1966+
match(where("itemId").is("1").and("tags").is("c")));
1967+
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, Document.class);
1968+
List<Document> mappedResults = results.getMappedResults();
1969+
assertThat(mappedResults).hasSize(1);
1970+
assertThat(mappedResults.get(0)).containsEntry("item_id", "1");
1971+
}
1972+
19551973
private void createUsersWithReferencedPersons() {
19561974

19571975
mongoTemplate.dropCollection(User.class);
@@ -2204,7 +2222,7 @@ static class Sales {
22042222
List<Item> items;
22052223
}
22062224

2207-
// DATAMONGO-1491
2225+
// DATAMONGO-1491, GH-4443
22082226
@lombok.Data
22092227
@Builder
22102228
static class Item {
@@ -2213,6 +2231,7 @@ static class Item {
22132231
String itemId;
22142232
Integer quantity;
22152233
Long price;
2234+
List<String> tags = new ArrayList<>();
22162235
}
22172236

22182237
// DATAMONGO-1538

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

+20-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* @author Thomas Darimont
5050
* @author Christoph Strobl
5151
* @author Mark Paluch
52+
* @author Julia Lee
5253
*/
5354
public class AggregationUnitTests {
5455

@@ -612,7 +613,7 @@ void shouldNotConvertIncludeExcludeValuesForProjectOperation() {
612613
WithRetypedIdField.class, mappingContext,
613614
new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)));
614615
Document document = project(WithRetypedIdField.class).toDocument(context);
615-
assertThat(document).isEqualTo(new Document("$project", new Document("_id", 1).append("renamed-field", 1)));
616+
assertThat(document).isEqualTo(new Document("$project", new Document("_id", 1).append("renamed-field", 1).append("entries", 1)));
616617
}
617618

618619
@Test // GH-4038
@@ -653,6 +654,22 @@ void inheritedFieldsExposingContextShouldNotFailOnUnknownFieldReferenceForRelaxe
653654
assertThat(documents.get(2)).isEqualTo("{ $sort : { 'serial_number' : -1, 'label_name' : -1 } }");
654655
}
655656

657+
@Test // GH-4443
658+
void fieldsExposingContextShouldUseCustomFieldNameFromRelaxedRootContext() {
659+
660+
MongoMappingContext mappingContext = new MongoMappingContext();
661+
RelaxedTypeBasedAggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(
662+
WithRetypedIdField.class, mappingContext,
663+
new QueryMapper(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)));
664+
665+
TypedAggregation<WithRetypedIdField> agg = newAggregation(WithRetypedIdField.class,
666+
unwind("entries"), match(where("foo").is("value 2")));
667+
List<Document> pipeline = agg.toPipeline(context);
668+
669+
Document fields = getAsDocument(pipeline.get(1), "$match");
670+
assertThat(fields.get("renamed-field")).isEqualTo("value 2");
671+
}
672+
656673
private Document extractPipelineElement(Document agg, int index, String operation) {
657674

658675
List<Document> pipeline = (List<Document>) agg.get("pipeline");
@@ -672,5 +689,7 @@ public class WithRetypedIdField {
672689

673690
@org.springframework.data.mongodb.core.mapping.Field("renamed-field") private String foo;
674691

692+
private List<String> entries = new ArrayList<>();
693+
675694
}
676695
}

0 commit comments

Comments
 (0)