1515 */
1616package org .springframework .data .mongodb .core .aggregation ;
1717
18- import static org .mockito .Mockito .*;
19- import static org .springframework .data .domain .Sort .Direction .*;
20- import static org .springframework .data .mongodb .core .aggregation .Aggregation .*;
21-
18+ import static org .mockito .Mockito .eq ;
19+ import static org .mockito .Mockito .mock ;
20+ import static org .mockito .Mockito .verify ;
21+ import static org .springframework .data .domain .Sort .Direction .DESC ;
22+ import static org .springframework .data .mongodb .core .aggregation .Aggregation .project ;
23+ import static org .springframework .data .mongodb .core .aggregation .Aggregation .sort ;
24+
25+ import java .time .ZonedDateTime ;
2226import java .util .List ;
27+ import java .util .Set ;
2328
29+ import org .assertj .core .api .Assertions ;
30+ import org .bson .Document ;
2431import org .junit .jupiter .api .Test ;
25-
2632import org .springframework .data .annotation .Id ;
33+ import org .springframework .data .convert .ConverterBuilder ;
34+ import org .springframework .data .convert .CustomConversions ;
35+ import org .springframework .data .convert .CustomConversions .StoreConversions ;
36+ import org .springframework .data .domain .Sort .Direction ;
2737import org .springframework .data .mongodb .core .convert .MappingMongoConverter ;
2838import org .springframework .data .mongodb .core .convert .NoOpDbRefResolver ;
2939import org .springframework .data .mongodb .core .convert .QueryMapper ;
40+ import org .springframework .data .mongodb .core .query .Criteria ;
3041import org .springframework .data .mongodb .test .util .MongoTestMappingContext ;
3142
3243/**
@@ -47,32 +58,56 @@ void nonFieldsExposingAggregationOperationContinuesWithSameContextForNextStage()
4758 verify (stage2 ).toPipelineStages (eq (rootContext ));
4859 }
4960
50- record TestRecord (@ Id String field1 , String field2 , LayerOne layerOne ) {
51- record LayerOne (List <LayerTwo > layerTwo ) {
52- }
61+ @ Test
62+ void contextShouldCarryOnRelaxedFieldMapping () {
5363
54- record LayerTwo (LayerThree layerThree ) {
55- }
64+ MongoTestMappingContext ctx = new MongoTestMappingContext (cfg -> {
65+ cfg .initialEntitySet (TestRecord .class );
66+ });
67+
68+ MappingMongoConverter mongoConverter = new MappingMongoConverter (NoOpDbRefResolver .INSTANCE , ctx );
5669
57- record LayerThree (int fieldA , int fieldB )
58- {}
70+ Aggregation agg = Aggregation .newAggregation (Aggregation .unwind ("layerOne.layerTwo" ),
71+ project ().and ("layerOne.layerTwo.layerThree" ).as ("layerOne.layerThree" ),
72+ sort (DESC , "layerOne.layerThree.fieldA" ));
73+
74+ AggregationOperationRenderer .toDocument (agg .getPipeline ().getOperations (),
75+ new RelaxedTypeBasedAggregationOperationContext (TestRecord .class , ctx , new QueryMapper (mongoConverter )));
5976 }
6077
61- @ Test
62- void xxx () {
78+ @ Test // GH-4722
79+ void appliesConversionToValuesUsedInAggregation () {
6380
6481 MongoTestMappingContext ctx = new MongoTestMappingContext (cfg -> {
6582 cfg .initialEntitySet (TestRecord .class );
6683 });
6784
6885 MappingMongoConverter mongoConverter = new MappingMongoConverter (NoOpDbRefResolver .INSTANCE , ctx );
69-
70- Aggregation agg = Aggregation .newAggregation (
71- Aggregation .unwind ("layerOne.layerTwo" ),
72- project ().and ("layerOne.layerTwo.layerThree" ).as ("layerOne.layerThree" ),
73- sort (DESC , "layerOne.layerThree.fieldA" )
86+ mongoConverter .setCustomConversions (new CustomConversions (StoreConversions .NONE ,
87+ Set .copyOf (ConverterBuilder .writing (ZonedDateTime .class , String .class , ZonedDateTime ::toString )
88+ .andReading (it -> ZonedDateTime .parse (it )).getConverters ())));
89+ mongoConverter .afterPropertiesSet ();
90+
91+ var agg = Aggregation .newAggregation (Aggregation .sort (Direction .DESC , "version" ),
92+ Aggregation .group ("entityId" ).first (Aggregation .ROOT ).as ("value" ), Aggregation .replaceRoot ("value" ),
93+ Aggregation .match (Criteria .where ("createdDate" ).lt (ZonedDateTime .now ())) // here is the problem
7494 );
7595
76- AggregationOperationRenderer .toDocument (agg .getPipeline ().getOperations (), new RelaxedTypeBasedAggregationOperationContext (TestRecord .class , ctx , new QueryMapper (mongoConverter )));
96+ List <Document > document = AggregationOperationRenderer .toDocument (agg .getPipeline ().getOperations (),
97+ new RelaxedTypeBasedAggregationOperationContext (TestRecord .class , ctx , new QueryMapper (mongoConverter )));
98+ Assertions .assertThat (document ).last ()
99+ .extracting (it -> it .getEmbedded (List .of ("$match" , "createdDate" , "$lt" ), Object .class ))
100+ .isInstanceOf (String .class );
101+ }
102+
103+ record TestRecord (@ Id String field1 , String field2 , LayerOne layerOne ) {
104+ record LayerOne (List <LayerTwo > layerTwo ) {
105+ }
106+
107+ record LayerTwo (LayerThree layerThree ) {
108+ }
109+
110+ record LayerThree (int fieldA , int fieldB ) {
111+ }
77112 }
78113}
0 commit comments