diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java
index 7dbed3a85..9d0ddf6d6 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/OutOperation.java
@@ -17,7 +17,7 @@ package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.jspecify.annotations.Nullable;
-import org.springframework.data.mongodb.util.BsonUtils;
+
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -37,33 +37,25 @@ public class OutOperation implements AggregationOperation {
private final @Nullable String databaseName;
private final String collectionName;
- private final @Nullable Document uniqueKey;
- private final @Nullable OutMode mode;
/**
* @param outCollectionName Collection name to export the results. Must not be {@literal null}.
*/
public OutOperation(String outCollectionName) {
- this(null, outCollectionName, null, null);
+ this(null, outCollectionName);
}
/**
* @param databaseName Optional database name the target collection is located in. Can be {@literal null}.
* @param collectionName Collection name to export the results. Must not be {@literal null}. Can be {@literal null}.
- * @param uniqueKey Optional unique key spec identify a document in the to collection for replacement or merge.
- * @param mode The mode for merging the aggregation pipeline output with the target collection. Can be
- * {@literal null}. {@literal null}.
* @since 2.2
*/
- private OutOperation(@Nullable String databaseName, String collectionName, @Nullable Document uniqueKey,
- @Nullable OutMode mode) {
+ private OutOperation(@Nullable String databaseName, String collectionName) {
Assert.notNull(collectionName, "Collection name must not be null");
this.databaseName = databaseName;
this.collectionName = collectionName;
- this.uniqueKey = uniqueKey;
- this.mode = mode;
}
/**
@@ -76,187 +68,21 @@ public class OutOperation implements AggregationOperation {
*/
@Contract("_ -> new")
public OutOperation in(@Nullable String database) {
- return new OutOperation(database, collectionName, uniqueKey, mode);
- }
-
- /**
- * Optionally specify the field that uniquely identifies a document in the target collection.
- * For convenience the given {@literal key} can either be a single field name or the Json representation of a key
- * {@link Document}.
- *
- *
- *
- * // {
- * // "field-1" : 1
- * // }
- * .uniqueKey("field-1")
- *
- * // {
- * // "field-1" : 1,
- * // "field-2" : 1
- * // }
- * .uniqueKey("{ 'field-1' : 1, 'field-2' : 1}")
- *
- *
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @param key can be {@literal null}. Server uses {@literal _id} when {@literal null}.
- * @return new instance of {@link OutOperation}.
- * @since 2.2
- */
- @Contract("_ -> new")
- public OutOperation uniqueKey(@Nullable String key) {
-
- Document uniqueKey = key == null ? null : BsonUtils.toDocumentOrElse(key, it -> new Document(it, 1));
- return new OutOperation(databaseName, collectionName, uniqueKey, mode);
- }
-
- /**
- * Optionally specify the fields that uniquely identifies a document in the target collection.
- *
- *
- *
- * // {
- * // "field-1" : 1
- * // "field-2" : 1
- * // }
- * .uniqueKeyOf(Arrays.asList("field-1", "field-2"))
- *
- *
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @param fields must not be {@literal null}.
- * @return new instance of {@link OutOperation}.
- * @since 2.2
- */
- @Contract("_ -> new")
- public OutOperation uniqueKeyOf(Iterable fields) {
-
- Assert.notNull(fields, "Fields must not be null");
-
- Document uniqueKey = new Document();
- fields.forEach(it -> uniqueKey.append(it, 1));
-
- return new OutOperation(databaseName, collectionName, uniqueKey, mode);
- }
-
- /**
- * Specify how to merge the aggregation output with the target collection.
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @param mode must not be {@literal null}.
- * @return new instance of {@link OutOperation}.
- * @since 2.2
- */
- @Contract("_ -> new")
- public OutOperation mode(OutMode mode) {
-
- Assert.notNull(mode, "Mode must not be null");
- return new OutOperation(databaseName, collectionName, uniqueKey, mode);
- }
-
- /**
- * Replace the target collection.
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @return new instance of {@link OutOperation}.
- * @see OutMode#REPLACE_COLLECTION
- * @since 2.2
- */
- @Contract("-> new")
- public OutOperation replaceCollection() {
- return mode(OutMode.REPLACE_COLLECTION);
- }
-
- /**
- * Replace/Upsert documents in the target collection.
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @return new instance of {@link OutOperation}.
- * @see OutMode#REPLACE
- * @since 2.2
- */
- @Contract("-> new")
- public OutOperation replaceDocuments() {
- return mode(OutMode.REPLACE);
- }
-
- /**
- * Insert documents to the target collection.
- * NOTE: Requires MongoDB 4.2 or later.
- *
- * @return new instance of {@link OutOperation}.
- * @see OutMode#INSERT
- * @since 2.2
- */
- @Contract("-> new")
- public OutOperation insertDocuments() {
- return mode(OutMode.INSERT);
+ return new OutOperation(database, collectionName);
}
@Override
public Document toDocument(AggregationOperationContext context) {
- if (!requiresMongoDb42Format()) {
- return new Document("$out", collectionName);
+ if (!StringUtils.hasText(databaseName)) {
+ return new Document(getOperator(), collectionName);
}
- Assert.state(mode != null, "Mode must not be null");
-
- Document $out = new Document("to", collectionName) //
- .append("mode", mode.getMongoMode());
-
- if (StringUtils.hasText(databaseName)) {
- $out.append("db", databaseName);
- }
-
- if (uniqueKey != null) {
- $out.append("uniqueKey", uniqueKey);
- }
-
- return new Document(getOperator(), $out);
+ return new Document(getOperator(), new Document("db", databaseName).append("coll", collectionName));
}
@Override
public String getOperator() {
return "$out";
}
-
- private boolean requiresMongoDb42Format() {
- return StringUtils.hasText(databaseName) || mode != null || uniqueKey != null;
- }
-
- /**
- * The mode for merging the aggregation pipeline output.
- *
- * @author Christoph Strobl
- * @since 2.2
- */
- public enum OutMode {
-
- /**
- * Write documents to the target collection. Errors if a document same uniqueKey already exists.
- */
- INSERT("insertDocuments"),
-
- /**
- * Update on any document in the target collection with the same uniqueKey.
- */
- REPLACE("replaceDocuments"),
-
- /**
- * Replaces the to collection with the output from the aggregation pipeline. Cannot be in a different database.
- */
- REPLACE_COLLECTION("replaceCollection");
-
- private final String mode;
-
- OutMode(String mode) {
- this.mode = mode;
- }
-
- public String getMongoMode() {
- return mode;
- }
- }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java
index f8812448b..a86433175 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/OutOperationUnitTest.java
@@ -18,8 +18,6 @@ package org.springframework.data.mongodb.core.aggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.test.util.Assertions.*;
-import java.util.Arrays;
-
import org.bson.Document;
import org.junit.jupiter.api.Test;
@@ -30,65 +28,24 @@ import org.junit.jupiter.api.Test;
* @author Christoph Strobl
* @author Mark Paluch
*/
-public class OutOperationUnitTest {
+class OutOperationUnitTest {
@Test // DATAMONGO-1418
- public void shouldCheckNPEInCreation() {
+ void shouldCheckNPEInCreation() {
assertThatIllegalArgumentException().isThrownBy(() -> new OutOperation(null));
}
@Test // DATAMONGO-2259
- public void shouldUsePreMongoDB42FormatWhenOnlyCollectionIsPresent() {
+ void shouldUsePreMongoDB42FormatWhenOnlyCollectionIsPresent() {
assertThat(out("out-col").toDocument(Aggregation.DEFAULT_CONTEXT)).isEqualTo(new Document("$out", "out-col"));
}
- @Test // DATAMONGO-2259
- public void shouldUseMongoDB42ExtendedFormatWhenAdditionalParametersPresent() {
-
- assertThat(out("out-col").insertDocuments().toDocument(Aggregation.DEFAULT_CONTEXT))
- .isEqualTo(new Document("$out", new Document("to", "out-col").append("mode", "insertDocuments")));
- }
-
- @Test // DATAMONGO-2259
- public void shouldRenderExtendedFormatWithJsonStringKey() {
-
- assertThat(out("out-col").insertDocuments() //
- .in("database-2") //
- .uniqueKey("{ 'field-1' : 1, 'field-2' : 1}") //
- .toDocument(Aggregation.DEFAULT_CONTEXT)) //
- .containsEntry("$out.to", "out-col") //
- .containsEntry("$out.mode", "insertDocuments") //
- .containsEntry("$out.db", "database-2") //
- .containsEntry("$out.uniqueKey", new Document("field-1", 1).append("field-2", 1));
- }
-
- @Test // DATAMONGO-2259
- public void shouldRenderExtendedFormatWithSingleFieldKey() {
-
- assertThat(out("out-col").insertDocuments().in("database-2") //
- .uniqueKey("field-1").toDocument(Aggregation.DEFAULT_CONTEXT)) //
- .containsEntry("$out.to", "out-col") //
- .containsEntry("$out.mode", "insertDocuments") //
- .containsEntry("$out.db", "database-2") //
- .containsEntry("$out.uniqueKey", new Document("field-1", 1));
- }
-
- @Test // DATAMONGO-2259
- public void shouldRenderExtendedFormatWithMultiFieldKey() {
-
- assertThat(out("out-col").insertDocuments().in("database-2") //
- .uniqueKeyOf(Arrays.asList("field-1", "field-2")) //
- .toDocument(Aggregation.DEFAULT_CONTEXT)).containsEntry("$out.to", "out-col") //
- .containsEntry("$out.mode", "insertDocuments") //
- .containsEntry("$out.db", "database-2") //
- .containsEntry("$out.uniqueKey", new Document("field-1", 1).append("field-2", 1));
- }
-
- @Test // DATAMONGO-2259
- public void shouldErrorOnExtendedFormatWithoutMode() {
+ @Test // DATAMONGO-2259, GH-4969
+ void shouldRenderDocument() {
- assertThatThrownBy(() -> out("out-col").in("database-2").toDocument(Aggregation.DEFAULT_CONTEXT))
- .isInstanceOf(IllegalStateException.class);
+ assertThat(out("out-col").in("database-2").toDocument(Aggregation.DEFAULT_CONTEXT))
+ .containsEntry("$out.coll", "out-col") //
+ .containsEntry("$out.db", "database-2");
}
}