DATAMONGO-1550 - Polishing $replaceRoot (aggregation stage).
Original Pull Request: #422.
This commit is contained in:
@@ -28,13 +28,14 @@ import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Encapsulates the aggregation framework {@code $replaceRoot}-operation.
|
||||
* <p>
|
||||
* Encapsulates the aggregation framework {@code $replaceRoot}-operation. <br />
|
||||
* We recommend to use the static factory method {@link Aggregation#replaceRoot(String)} instead of creating instances
|
||||
* of this class directly.
|
||||
*
|
||||
* @see https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/#pipe._S_replaceRoot
|
||||
*
|
||||
* @see <a href=
|
||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/">https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/</a>
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @since 1.10
|
||||
*/
|
||||
public class ReplaceRootOperation implements FieldsExposingAggregationOperation {
|
||||
@@ -42,32 +43,37 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
private final Replacement replacement;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReplaceRootOperation} given the {@link as} field name.
|
||||
* Creates a new {@link ReplaceRootOperation} given the {@link Field} field name.
|
||||
*
|
||||
* @param field must not be {@literal null} or empty.
|
||||
*/
|
||||
public ReplaceRootOperation(Field field) {
|
||||
this.replacement = new FieldReplacement(field);
|
||||
this(new FieldReplacement(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReplaceRootOperation} given the {@link as} field name.
|
||||
* Creates a new {@link ReplaceRootOperation} given the {@link AggregationExpression} pointing to a document.
|
||||
*
|
||||
* @param aggregationExpression must not be {@literal null}.
|
||||
*/
|
||||
public ReplaceRootOperation(AggregationExpression aggregationExpression) {
|
||||
|
||||
Assert.notNull(aggregationExpression, "AggregationExpression must not be null!");
|
||||
this.replacement = new AggregationExpressionReplacement(aggregationExpression);
|
||||
this(new AggregationExpressionReplacement(aggregationExpression));
|
||||
}
|
||||
|
||||
protected ReplaceRootOperation(Replacement replacement) {
|
||||
/**
|
||||
* Creates a new {@link ReplaceRootOperation} given the {@link Replacement}.
|
||||
*
|
||||
* @param replacement must not be {@literal null}.
|
||||
*/
|
||||
public ReplaceRootOperation(Replacement replacement) {
|
||||
|
||||
Assert.notNull(replacement, "Replacement must not be null!");
|
||||
this.replacement = replacement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReplaceRootDocumentOperationBuilder}.
|
||||
*
|
||||
*
|
||||
* @return a new {@link ReplaceRootDocumentOperationBuilder}.
|
||||
*/
|
||||
public static ReplaceRootOperationBuilder builder() {
|
||||
@@ -79,7 +85,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
*/
|
||||
@Override
|
||||
public DBObject toDBObject(AggregationOperationContext context) {
|
||||
return new BasicDBObject("$replaceRoot", new BasicDBObject("newRoot", replacement.toObject(context)));
|
||||
return new BasicDBObject("$replaceRoot", new BasicDBObject("newRoot", replacement.toDocumentExpression(context)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -99,7 +105,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
|
||||
/**
|
||||
* Defines a root document replacement based on a {@literal fieldName} that resolves to a document.
|
||||
*
|
||||
*
|
||||
* @param fieldName must not be {@literal null} or empty.
|
||||
* @return the final {@link ReplaceRootOperation}.
|
||||
*/
|
||||
@@ -118,8 +124,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a root document replacement based on a composable document that is empty initially.
|
||||
* <p>
|
||||
* Defines a root document replacement based on a composable document that is empty initially. <br />
|
||||
* {@link ReplaceRootOperation} can be populated with individual entries and derive its values from other, existing
|
||||
* documents.
|
||||
*
|
||||
@@ -130,8 +135,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a root document replacement based on a composable document given {@literal dbObject}
|
||||
* <p>
|
||||
* Defines a root document replacement based on a composable document given {@literal dbObject}. <br />
|
||||
* {@link ReplaceRootOperation} can be populated with individual entries and derive its values from other, existing
|
||||
* documents.
|
||||
*
|
||||
@@ -148,8 +152,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
|
||||
/**
|
||||
* Encapsulates the aggregation framework {@code $replaceRoot}-operation to result in a composable replacement
|
||||
* document.
|
||||
* <p>
|
||||
* document. <br />
|
||||
* Instances of {@link ReplaceRootDocumentOperation} yield empty upon construction and can be populated with single
|
||||
* values and documents.
|
||||
*
|
||||
@@ -175,7 +178,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
/**
|
||||
* Creates an extended {@link ReplaceRootDocumentOperation} that combines {@link ReplacementDocument}s from the
|
||||
* {@literal currentOperation} and {@literal extension} operation.
|
||||
*
|
||||
*
|
||||
* @param currentOperation must not be {@literal null}.
|
||||
* @param extension must not be {@literal null}.
|
||||
*/
|
||||
@@ -185,9 +188,9 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReplaceRootDocumentOperationBuilder} to define a field for the {@link AggregationExpression}
|
||||
* .
|
||||
*
|
||||
* Creates a new {@link ReplaceRootDocumentOperationBuilder} to define a field for the
|
||||
* {@link AggregationExpression}.
|
||||
*
|
||||
* @param aggregationExpression must not be {@literal null}.
|
||||
* @return the {@link ReplaceRootDocumentOperationBuilder}.
|
||||
*/
|
||||
@@ -251,17 +254,18 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* Replacement object that results in a replacement document or an expression that results in a document.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private abstract static class Replacement {
|
||||
public interface Replacement {
|
||||
|
||||
/**
|
||||
* Renders the current {@link Replacement} into a {@link DBObject} based on the given
|
||||
* Renders the current {@link Replacement} into a its MongoDB representation based on the given
|
||||
* {@link AggregationOperationContext}.
|
||||
*
|
||||
* @param context will never be {@literal null}.
|
||||
* @return a replacement document or an expression that results in a document.
|
||||
*/
|
||||
public abstract Object toObject(AggregationOperationContext context);
|
||||
Object toDocumentExpression(AggregationOperationContext context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,11 +273,13 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
private static class AggregationExpressionReplacement extends Replacement {
|
||||
private static class AggregationExpressionReplacement implements Replacement {
|
||||
|
||||
private final AggregationExpression aggregationExpression;
|
||||
|
||||
protected AggregationExpressionReplacement(AggregationExpression aggregationExpression) {
|
||||
|
||||
Assert.notNull(aggregationExpression, "AggregationExpression must not be null!");
|
||||
this.aggregationExpression = aggregationExpression;
|
||||
}
|
||||
|
||||
@@ -281,17 +287,17 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public DBObject toObject(AggregationOperationContext context) {
|
||||
public DBObject toDocumentExpression(AggregationOperationContext context) {
|
||||
return aggregationExpression.toDbObject(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Replacement that references a {@link Field} inside the current aggregation pipeline.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
private static class FieldReplacement extends Replacement {
|
||||
private static class FieldReplacement implements Replacement {
|
||||
|
||||
private final Field field;
|
||||
|
||||
@@ -308,7 +314,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public Object toObject(AggregationOperationContext context) {
|
||||
public Object toDocumentExpression(AggregationOperationContext context) {
|
||||
return context.getReference(field).toString();
|
||||
}
|
||||
}
|
||||
@@ -318,7 +324,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
private static class ReplacementDocument extends Replacement {
|
||||
private static class ReplacementDocument implements Replacement {
|
||||
|
||||
private final Collection<ReplacementContributor> replacements;
|
||||
|
||||
@@ -378,12 +384,12 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.Replacement#toObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public DBObject toObject(AggregationOperationContext context) {
|
||||
public DBObject toDocumentExpression(AggregationOperationContext context) {
|
||||
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
|
||||
for (ReplacementContributor replacement : replacements) {
|
||||
dbObject.putAll(replacement.toDBObject(context));
|
||||
dbObject.putAll(replacement.toDbObject(context));
|
||||
}
|
||||
|
||||
return dbObject;
|
||||
@@ -403,7 +409,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
ReplacementDocument replacementDocument = new ReplacementDocument();
|
||||
|
||||
List<ReplacementContributor> replacements = new ArrayList<ReplacementContributor>(
|
||||
this.replacements.size() + replacementDocument.replacements.size());
|
||||
this.replacements.size() + extension.replacements.size());
|
||||
|
||||
replacements.addAll(this.replacements);
|
||||
replacements.addAll(extension.replacements);
|
||||
@@ -414,10 +420,10 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
|
||||
/**
|
||||
* Partial {@link DBObject} contributor for document replacement.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
private abstract static class ReplacementContributor {
|
||||
private interface ReplacementContributor extends AggregationExpression {
|
||||
|
||||
/**
|
||||
* Renders the current {@link ReplacementContributor} into a {@link DBObject} based on the given
|
||||
@@ -426,17 +432,17 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @param context will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public abstract DBObject toDBObject(AggregationOperationContext context);
|
||||
DBObject toDbObject(AggregationOperationContext context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ReplacementContributor} to contribute multiple fields based on the input {@literal value}.
|
||||
* <p>
|
||||
* {@link ReplacementContributor} to contribute multiple fields based on the input {@literal value}. <br />
|
||||
* The value object is mapped into a MongoDB {@link DBObject}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private static class DocumentContributor extends ReplacementContributor {
|
||||
private static class DocumentContributor implements ReplacementContributor {
|
||||
|
||||
private final Object value;
|
||||
|
||||
@@ -455,11 +461,13 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplacementContributor#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public DBObject toDBObject(AggregationOperationContext context) {
|
||||
public DBObject toDbObject(AggregationOperationContext context) {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("$set", value);
|
||||
if (value instanceof DBObject) {
|
||||
return (DBObject) value;
|
||||
}
|
||||
|
||||
return (DBObject) context.getMappedObject(dbObject).get("$set");
|
||||
return (DBObject) context.getMappedObject(new BasicDBObject("$set", value)).get("$set");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +477,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
private abstract static class FieldContributorSupport extends ReplacementContributor {
|
||||
private abstract static class FieldContributorSupport implements ReplacementContributor {
|
||||
|
||||
private final ExposedField field;
|
||||
|
||||
@@ -521,10 +529,12 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplacementContributor#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public DBObject toDBObject(AggregationOperationContext context) {
|
||||
public DBObject toDbObject(AggregationOperationContext context) {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("$set", value);
|
||||
return new BasicDBObject(getField().getTarget(), context.getMappedObject(dbObject).get("$set"));
|
||||
Object mappedValue = value instanceof BasicDBObject ? value
|
||||
: context.getMappedObject(new BasicDBObject("$set", value)).get("$set");
|
||||
|
||||
return new BasicDBObject(getField().getTarget(), mappedValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +567,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
|
||||
* @see org.springframework.data.mongodb.core.aggregation.ReplaceRootOperation.ReplacementContributor#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@Override
|
||||
public DBObject toDBObject(AggregationOperationContext context) {
|
||||
public DBObject toDbObject(AggregationOperationContext context) {
|
||||
return new BasicDBObject(getField().getTarget(), aggregationExpression.toDbObject(context));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ReplaceRootOperation}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ReplaceRootOperationUnitTests {
|
||||
|
||||
Reference in New Issue
Block a user