20
20
import java .util .Collections ;
21
21
import java .util .LinkedHashMap ;
22
22
import java .util .List ;
23
- import java .util .Map ;
24
23
25
24
import org .springframework .data .mongodb .core .aggregation .AggregationExpressions .Filter .AsBuilder ;
25
+ import org .springframework .data .mongodb .core .aggregation .AggregationExpressions .Map .ArrayOfBuilder ;
26
26
import org .springframework .data .mongodb .core .aggregation .ExposedFields .ExposedField ;
27
27
import org .springframework .data .mongodb .core .aggregation .ExposedFields .FieldReference ;
28
28
import org .springframework .util .Assert ;
@@ -1781,6 +1781,24 @@ private boolean usesFieldRef() {
1781
1781
}
1782
1782
}
1783
1783
1784
+ /**
1785
+ * Gateway to {@literal Date} aggregation operations.
1786
+ *
1787
+ * @author Christoph Strobl
1788
+ */
1789
+ class VariableOperators {
1790
+
1791
+ /**
1792
+ * Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array
1793
+ * and returns an array with the applied results.
1794
+ *
1795
+ * @return
1796
+ */
1797
+ public static ArrayOfBuilder map () {
1798
+ return Map .map ();
1799
+ }
1800
+ }
1801
+
1784
1802
/**
1785
1803
* @author Christoph Strobl
1786
1804
*/
@@ -1809,10 +1827,10 @@ public DBObject toDbObject(Object value, AggregationOperationContext context) {
1809
1827
args .add (unpack (val , context ));
1810
1828
}
1811
1829
valueToUse = args ;
1812
- } else if (value instanceof Map ) {
1830
+ } else if (value instanceof java . util . Map ) {
1813
1831
1814
1832
DBObject dbo = new BasicDBObject ();
1815
- for (Map .Entry <String , Object > entry : ((Map <String , Object >) value ).entrySet ()) {
1833
+ for (java . util . Map .Entry <String , Object > entry : ((java . util . Map <String , Object >) value ).entrySet ()) {
1816
1834
dbo .put (entry .getKey (), unpack (entry .getValue (), context ));
1817
1835
}
1818
1836
valueToUse = dbo ;
@@ -1866,10 +1884,10 @@ protected List<Object> append(Object value) {
1866
1884
1867
1885
protected Object append (String key , Object value ) {
1868
1886
1869
- if (!(value instanceof Map )) {
1887
+ if (!(value instanceof java . util . Map )) {
1870
1888
throw new IllegalArgumentException ("o_O" );
1871
1889
}
1872
- Map <String , Object > clone = new LinkedHashMap <String , Object >((Map <String , Object >) value );
1890
+ java . util . Map <String , Object > clone = new LinkedHashMap <String , Object >((java . util . Map <String , Object >) value );
1873
1891
clone .put (key , value );
1874
1892
return clone ;
1875
1893
@@ -2344,6 +2362,7 @@ public static Abs absoluteValueOf(AggregationExpression expression) {
2344
2362
Assert .notNull (expression , "Expression must not be null!" );
2345
2363
return new Abs (expression );
2346
2364
}
2365
+
2347
2366
/**
2348
2367
* Creates new {@link Abs}.
2349
2368
*
@@ -2495,7 +2514,6 @@ protected String getMongoMethod() {
2495
2514
return "$divide" ;
2496
2515
}
2497
2516
2498
-
2499
2517
/**
2500
2518
* Creates new {@link Divide}.
2501
2519
*
@@ -4390,7 +4408,7 @@ protected String getMongoMethod() {
4390
4408
4391
4409
/**
4392
4410
* Creates new {@link Second}.
4393
- *
4411
+ *
4394
4412
* @param fieldReference must not be {@literal null}.
4395
4413
* @return
4396
4414
*/
@@ -4509,9 +4527,9 @@ public DateToString toString(String format) {
4509
4527
};
4510
4528
}
4511
4529
4512
- private static Map <String , Object > argumentMap (Object date , String format ) {
4530
+ private static java . util . Map <String , Object > argumentMap (Object date , String format ) {
4513
4531
4514
- Map <String , Object > args = new LinkedHashMap <String , Object >(2 );
4532
+ java . util . Map <String , Object > args = new LinkedHashMap <String , Object >(2 );
4515
4533
args .put ("format" , format );
4516
4534
args .put ("date" , date );
4517
4535
return args ;
@@ -4705,7 +4723,7 @@ protected String getMongoMethod() {
4705
4723
4706
4724
/**
4707
4725
* Creates new {@link Max}.
4708
- *
4726
+ *
4709
4727
* @param fieldReference must not be {@literal null}.
4710
4728
* @return
4711
4729
*/
@@ -4730,7 +4748,7 @@ public static Max maxOf(AggregationExpression expression) {
4730
4748
/**
4731
4749
* Creates new {@link Max} with all previously added arguments appending the given one. <br />
4732
4750
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
4733
- *
4751
+ *
4734
4752
* @param fieldReference must not be {@literal null}.
4735
4753
* @return
4736
4754
*/
@@ -4809,7 +4827,7 @@ public static Min minOf(AggregationExpression expression) {
4809
4827
/**
4810
4828
* Creates new {@link Min} with all previously added arguments appending the given one. <br />
4811
4829
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
4812
- *
4830
+ *
4813
4831
* @param fieldReference must not be {@literal null}.
4814
4832
* @return
4815
4833
*/
@@ -4942,7 +4960,7 @@ protected String getMongoMethod() {
4942
4960
4943
4961
/**
4944
4962
* Creates new {@link StdDevSamp}.
4945
- *
4963
+ *
4946
4964
* @param fieldReference must not be {@literal null}.
4947
4965
* @return
4948
4966
*/
@@ -5715,4 +5733,156 @@ public static Not not(AggregationExpression expression) {
5715
5733
}
5716
5734
}
5717
5735
5736
+ /**
5737
+ * {@link AggregationExpression} for {@code $map}.
5738
+ */
5739
+ class Map implements AggregationExpression {
5740
+
5741
+ private Object sourceArray ;
5742
+ private String itemVariableName ;
5743
+ private AggregationExpression functionToApply ;
5744
+
5745
+ private Map (Object sourceArray , String itemVariableName , AggregationExpression functionToApply ) {
5746
+
5747
+ Assert .notNull (sourceArray , "SourceArray must not be null!" );
5748
+ Assert .notNull (itemVariableName , "ItemVariableName must not be null!" );
5749
+ Assert .notNull (functionToApply , "FunctionToApply must not be null!" );
5750
+
5751
+ this .sourceArray = sourceArray ;
5752
+ this .itemVariableName = itemVariableName ;
5753
+ this .functionToApply = functionToApply ;
5754
+ }
5755
+
5756
+ /**
5757
+ * Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array
5758
+ * and returns an array with the applied results.
5759
+ *
5760
+ * @return
5761
+ */
5762
+ static ArrayOfBuilder map () {
5763
+
5764
+ return new ArrayOfBuilder () {
5765
+
5766
+ @ Override
5767
+ public AsBuilder itemsOf (final String fieldReference ) {
5768
+
5769
+ return new AsBuilder () {
5770
+
5771
+ @ Override
5772
+ public FunctionBuilder as (final String variableName ) {
5773
+
5774
+ return new FunctionBuilder () {
5775
+
5776
+ @ Override
5777
+ public Map andApply (final AggregationExpression expression ) {
5778
+ return new Map (Fields .field (fieldReference ), variableName , expression );
5779
+ }
5780
+ };
5781
+ }
5782
+ };
5783
+ }
5784
+
5785
+ @ Override
5786
+ public AsBuilder itemsOf (final AggregationExpression source ) {
5787
+
5788
+ return new AsBuilder () {
5789
+
5790
+ @ Override
5791
+ public FunctionBuilder as (final String variableName ) {
5792
+
5793
+ return new FunctionBuilder () {
5794
+
5795
+ @ Override
5796
+ public Map andApply (final AggregationExpression expression ) {
5797
+ return new Map (source , variableName , expression );
5798
+ }
5799
+ };
5800
+ }
5801
+ };
5802
+ }
5803
+ };
5804
+ };
5805
+
5806
+ @ Override
5807
+ public DBObject toDbObject (final AggregationOperationContext context ) {
5808
+
5809
+ return toMap (new ExposedFieldsAggregationOperationContext (
5810
+ ExposedFields .synthetic (Fields .fields (itemVariableName )), context ) {
5811
+
5812
+ @ Override
5813
+ public FieldReference getReference (Field field ) {
5814
+
5815
+ FieldReference ref = null ;
5816
+ try {
5817
+ ref = context .getReference (field );
5818
+ } catch (Exception e ) {
5819
+ // just ignore that one.
5820
+ }
5821
+ return ref != null ? ref : super .getReference (field );
5822
+ }
5823
+ });
5824
+ }
5825
+
5826
+ private DBObject toMap (AggregationOperationContext context ) {
5827
+
5828
+ BasicDBObject map = new BasicDBObject ();
5829
+
5830
+ BasicDBObject input ;
5831
+ if (sourceArray instanceof Field ) {
5832
+ input = new BasicDBObject ("input" , context .getReference ((Field ) sourceArray ).toString ());
5833
+ } else {
5834
+ input = new BasicDBObject ("input" , ((AggregationExpression ) sourceArray ).toDbObject (context ));
5835
+ }
5836
+
5837
+ map .putAll (context .getMappedObject (input ));
5838
+ map .put ("as" , itemVariableName );
5839
+ map .put ("in" , functionToApply .toDbObject (new NestedDelegatingExpressionAggregationOperationContext (context )));
5840
+
5841
+ return new BasicDBObject ("$map" , map );
5842
+ }
5843
+
5844
+ interface ArrayOfBuilder {
5845
+
5846
+ /**
5847
+ * Set the field that resolves to an array on which to apply the {@link AggregationExpression}.
5848
+ *
5849
+ * @param fieldReference must not be {@literal null}.
5850
+ * @return
5851
+ */
5852
+ AsBuilder itemsOf (String fieldReference );
5853
+
5854
+ /**
5855
+ * Set the {@link AggregationExpression} that results in an array on which to apply the
5856
+ * {@link AggregationExpression}.
5857
+ *
5858
+ * @param expression must not be {@literal null}.
5859
+ * @return
5860
+ */
5861
+ AsBuilder itemsOf (AggregationExpression expression );
5862
+ }
5863
+
5864
+ interface AsBuilder {
5865
+
5866
+ /**
5867
+ * Define the {@literal variableName} for addressing items within the array.
5868
+ *
5869
+ * @param variableName must not be {@literal null}.
5870
+ * @return
5871
+ */
5872
+ FunctionBuilder as (String variableName );
5873
+ }
5874
+
5875
+ interface FunctionBuilder {
5876
+
5877
+ /**
5878
+ * Creates new {@link Map} that applies the given {@link AggregationExpression} to each item of the referenced
5879
+ * array and returns an array with the applied results.
5880
+ *
5881
+ * @param expression must not be {@literal null}.
5882
+ * @return
5883
+ */
5884
+ Map andApply (AggregationExpression expression );
5885
+ }
5886
+ }
5887
+
5718
5888
}
0 commit comments