Skip to content

Commit adea4ba

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 529a0c7 commit adea4ba

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
@@ -91,6 +91,7 @@
9191
* @author Sergey Shcherbakov
9292
* @author Minsu Kim
9393
* @author Sangyong Choi
94+
* @author Julia Lee
9495
*/
9596
@ExtendWith(MongoTemplateExtension.class)
9697
public class AggregationTests {
@@ -119,7 +120,7 @@ private void cleanDb() {
119120

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

124125
mongoTemplate.dropCollection(INPUT_COLLECTION);
125126
mongoTemplate.dropCollection("personQueryTemp");
@@ -1992,6 +1993,23 @@ void considersMongoIdWithinTypedCollections() {
19921993
assertThat(aggregate.getMappedResults()).contains(widget);
19931994
}
19941995

1996+
@Test // GH-4443
1997+
void shouldHonorFieldAliasesForFieldReferencesUsingFieldExposingOperation() {
1998+
1999+
Item item1 = Item.builder().itemId("1").tags(Arrays.asList("a", "b")).build();
2000+
Item item2 = Item.builder().itemId("1").tags(Arrays.asList("a", "c")).build();
2001+
mongoTemplate.insert(Arrays.asList(item1, item2), Item.class);
2002+
2003+
TypedAggregation<Item> aggregation = newAggregation(Item.class,
2004+
match(where("itemId").is("1")),
2005+
unwind("tags"),
2006+
match(where("itemId").is("1").and("tags").is("c")));
2007+
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, Document.class);
2008+
List<Document> mappedResults = results.getMappedResults();
2009+
assertThat(mappedResults).hasSize(1);
2010+
assertThat(mappedResults.get(0)).containsEntry("item_id", "1");
2011+
}
2012+
19952013
private void createUsersWithReferencedPersons() {
19962014

19972015
mongoTemplate.dropCollection(User.class);
@@ -2244,7 +2262,7 @@ static class Sales {
22442262
List<Item> items;
22452263
}
22462264

2247-
// DATAMONGO-1491
2265+
// DATAMONGO-1491, GH-4443
22482266
@lombok.Data
22492267
@Builder
22502268
static class Item {
@@ -2253,6 +2271,7 @@ static class Item {
22532271
String itemId;
22542272
Integer quantity;
22552273
Long price;
2274+
List<String> tags = new ArrayList<>();
22562275
}
22572276

22582277
// 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)