|
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 |
|
| 24 | +import com.mongodb.BasicDBObject; |
| 25 | +import com.mongodb.DBObject; |
25 | 26 | import org.bson.Document;
|
26 | 27 | import org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Filter.AsBuilder;
|
| 28 | +import org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Map.ArrayOfBuilder; |
27 | 29 | import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
28 | 30 | import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
29 | 31 | import org.springframework.util.Assert;
|
@@ -1779,6 +1781,24 @@ private boolean usesFieldRef() {
|
1779 | 1781 | }
|
1780 | 1782 | }
|
1781 | 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 | + |
1782 | 1802 | /**
|
1783 | 1803 | * @author Christoph Strobl
|
1784 | 1804 | */
|
@@ -1807,10 +1827,10 @@ public Document toDocument(Object value, AggregationOperationContext context) {
|
1807 | 1827 | args.add(unpack(val, context));
|
1808 | 1828 | }
|
1809 | 1829 | valueToUse = args;
|
1810 |
| - } else if (value instanceof Map) { |
| 1830 | + } else if (value instanceof java.util.Map) { |
1811 | 1831 |
|
1812 | 1832 | Document dbo = new Document();
|
1813 |
| - 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()) { |
1814 | 1834 | dbo.put(entry.getKey(), unpack(entry.getValue(), context));
|
1815 | 1835 | }
|
1816 | 1836 | valueToUse = dbo;
|
@@ -1864,10 +1884,10 @@ protected List<Object> append(Object value) {
|
1864 | 1884 |
|
1865 | 1885 | protected Object append(String key, Object value) {
|
1866 | 1886 |
|
1867 |
| - if (!(value instanceof Map)) { |
| 1887 | + if (!(value instanceof java.util.Map)) { |
1868 | 1888 | throw new IllegalArgumentException("o_O");
|
1869 | 1889 | }
|
1870 |
| - 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); |
1871 | 1891 | clone.put(key, value);
|
1872 | 1892 | return clone;
|
1873 | 1893 |
|
@@ -2342,6 +2362,7 @@ public static Abs absoluteValueOf(AggregationExpression expression) {
|
2342 | 2362 | Assert.notNull(expression, "Expression must not be null!");
|
2343 | 2363 | return new Abs(expression);
|
2344 | 2364 | }
|
| 2365 | + |
2345 | 2366 | /**
|
2346 | 2367 | * Creates new {@link Abs}.
|
2347 | 2368 | *
|
@@ -2493,7 +2514,6 @@ protected String getMongoMethod() {
|
2493 | 2514 | return "$divide";
|
2494 | 2515 | }
|
2495 | 2516 |
|
2496 |
| - |
2497 | 2517 | /**
|
2498 | 2518 | * Creates new {@link Divide}.
|
2499 | 2519 | *
|
@@ -4507,9 +4527,9 @@ public DateToString toString(String format) {
|
4507 | 4527 | };
|
4508 | 4528 | }
|
4509 | 4529 |
|
4510 |
| - private static Map<String, Object> argumentMap(Object date, String format) { |
| 4530 | + private static java.util.Map<String, Object> argumentMap(Object date, String format) { |
4511 | 4531 |
|
4512 |
| - Map<String, Object> args = new LinkedHashMap<String, Object>(2); |
| 4532 | + java.util.Map<String, Object> args = new LinkedHashMap<String, Object>(2); |
4513 | 4533 | args.put("format", format);
|
4514 | 4534 | args.put("date", date);
|
4515 | 4535 | return args;
|
@@ -5713,4 +5733,156 @@ public static Not not(AggregationExpression expression) {
|
5713 | 5733 | }
|
5714 | 5734 | }
|
5715 | 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 Document toDocument(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 Document toMap(AggregationOperationContext context) { |
| 5827 | + |
| 5828 | + Document map = new Document(); |
| 5829 | + |
| 5830 | + Document input; |
| 5831 | + if (sourceArray instanceof Field) { |
| 5832 | + input = new Document("input", context.getReference((Field) sourceArray).toString()); |
| 5833 | + } else { |
| 5834 | + input = new Document("input", ((AggregationExpression) sourceArray).toDocument(context)); |
| 5835 | + } |
| 5836 | + |
| 5837 | + map.putAll(context.getMappedObject(input)); |
| 5838 | + map.put("as", itemVariableName); |
| 5839 | + map.put("in", functionToApply.toDocument(new NestedDelegatingExpressionAggregationOperationContext(context))); |
| 5840 | + |
| 5841 | + return new Document("$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 | + |
5716 | 5888 | }
|
0 commit comments