From 07830d96e78c96e4ef9dbdf5a08276f5ac4594a4 Mon Sep 17 00:00:00 2001 From: evanchooly Date: Sun, 12 May 2024 23:07:54 -0400 Subject: [PATCH] add a test for a new(?) example on $unionWith add support for invoking without a collection name or type --- .../codecs/stages/UnionWithCodec.java | 15 +++++++-- .../morphia/aggregation/stages/UnionWith.java | 32 ++++++++++++++++++- .../dev/morphia/test/TemplatedTestBase.java | 3 ++ .../aggregation/stages/TestUnionWith.java | 15 +++++++++ .../stages/unionWith/example3/data.json | 3 ++ .../stages/unionWith/example3/expected.json | 5 +++ .../stages/unionWith/example3/name | 1 + .../stages/unionWith/example3/pipeline.json | 12 +++++++ 8 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/data.json create mode 100644 core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/expected.json create mode 100644 core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/name create mode 100644 core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/pipeline.json diff --git a/core/src/main/java/dev/morphia/aggregation/codecs/stages/UnionWithCodec.java b/core/src/main/java/dev/morphia/aggregation/codecs/stages/UnionWithCodec.java index b517fd0c73d..1fadcef7a83 100644 --- a/core/src/main/java/dev/morphia/aggregation/codecs/stages/UnionWithCodec.java +++ b/core/src/main/java/dev/morphia/aggregation/codecs/stages/UnionWithCodec.java @@ -31,14 +31,23 @@ public Class getEncoderClass() { @Override protected void encodeStage(BsonWriter writer, UnionWith unionWith, EncoderContext encoderContext) { String name = unionWith.collectionName(); - String collectionName = name != null ? name - : getDatastore().getMapper().getEntityModel(unionWith.collectionType()).collectionName(); + Class type = unionWith.collectionType(); + final String collectionName; + if (name != null) { + collectionName = name; + } else if (type != null) { + collectionName = getDatastore().getMapper().getEntityModel(type).collectionName(); + } else { + collectionName = null; + } if (unionWith.pipeline().isEmpty()) { writer.writeString(collectionName); } else { document(writer, () -> { - value(writer, "coll", collectionName); + if (collectionName != null) { + value(writer, "coll", collectionName); + } value(getDatastore().getCodecRegistry(), writer, "pipeline", unionWith.pipeline(), encoderContext); }); } diff --git a/core/src/main/java/dev/morphia/aggregation/stages/UnionWith.java b/core/src/main/java/dev/morphia/aggregation/stages/UnionWith.java index 37849c5fa70..287d1323a7b 100644 --- a/core/src/main/java/dev/morphia/aggregation/stages/UnionWith.java +++ b/core/src/main/java/dev/morphia/aggregation/stages/UnionWith.java @@ -20,6 +20,19 @@ public class UnionWith extends Stage { private Class collectionType; private String collectionName; + /** + * Creates the new stage + * + * @param pipeline the pipeline + * @hidden + * @morphia.internal + */ + @MorphiaInternal + private UnionWith(List pipeline) { + super("$unionWith"); + this.pipeline = Collections.unmodifiableList(pipeline); + } + /** * Creates the new stage * @@ -54,13 +67,29 @@ private UnionWith(Class type, List pipeline) { * Performs a union of two collections; i.e. $unionWith combines pipeline results from two collections into a single result set. The * stage outputs the combined result set (including duplicates) to the next stage. * - * @param type the type to perform the pipeline against * @param stages the pipeline stages * * @return the new Stage * * @aggregation.stage $unionWith * @mongodb.server.release 4.4 + * @since 3.0 + */ + public static Stage unionWith(Stage... stages) { + return new UnionWith(Expressions.toList(stages)); + } + + /** + * Performs a union of two collections; i.e. $unionWith combines pipeline results from two collections into a single result set. The + * stage outputs the combined result set (including duplicates) to the next stage. + * + * @param type the type to perform the pipeline against + * @param stages the pipeline stages + * + * @return the new Stage + * + * @aggregation.stage $unionWith + * @mongodb.server.release 4.4 */ public static Stage unionWith(Class type, Stage... stages) { return new UnionWith(type, Expressions.toList(stages)); @@ -98,6 +127,7 @@ public String collectionName() { * @hidden * @morphia.internal */ + @Nullable @MorphiaInternal public Class collectionType() { return collectionType; diff --git a/core/src/test/java/dev/morphia/test/TemplatedTestBase.java b/core/src/test/java/dev/morphia/test/TemplatedTestBase.java index dcd93527ba6..be40bc09f11 100644 --- a/core/src/test/java/dev/morphia/test/TemplatedTestBase.java +++ b/core/src/test/java/dev/morphia/test/TemplatedTestBase.java @@ -175,6 +175,9 @@ protected List loadJson(String name, String type, boolean failOnMissin while (reader.ready()) { String json = reader.readLine(); try { + if (json.startsWith("[") && json.endsWith("]")) { + json = json.substring(1, json.length() - 1); + } data.add(Document.parse(json)); } catch (JsonParseException e) { throw new JsonParseException(e.getMessage() + "\n" + json, e); diff --git a/core/src/test/java/dev/morphia/test/aggregation/stages/TestUnionWith.java b/core/src/test/java/dev/morphia/test/aggregation/stages/TestUnionWith.java index 4effabf3bde..857be0c4f3d 100644 --- a/core/src/test/java/dev/morphia/test/aggregation/stages/TestUnionWith.java +++ b/core/src/test/java/dev/morphia/test/aggregation/stages/TestUnionWith.java @@ -6,6 +6,8 @@ import org.testng.annotations.Test; import static dev.morphia.aggregation.expressions.AccumulatorExpressions.sum; +import static dev.morphia.aggregation.expressions.Expressions.document; +import static dev.morphia.aggregation.stages.Documents.documents; import static dev.morphia.aggregation.stages.Group.group; import static dev.morphia.aggregation.stages.Group.id; import static dev.morphia.aggregation.stages.Set.set; @@ -42,4 +44,17 @@ public void testExample2() { .field("total", sum("$quantity")), sort().descending("total"))); } + + @Test + public void testExample3() { + testPipeline(ServerVersion.ANY, false, true, (aggregation) -> aggregation.pipeline( + unionWith( + documents( + document("_id", 4) + .field("flavor", "orange"), + document("_id", 5) + .field("flavor", "vanilla") + .field("price", 20))))); + } + } diff --git a/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/data.json b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/data.json new file mode 100644 index 00000000000..ef536df92f5 --- /dev/null +++ b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/data.json @@ -0,0 +1,3 @@ +{ _id: 1, flavor: "chocolate" }, +{ _id: 2, flavor: "strawberry" }, +{ _id: 3, flavor: "cherry" } \ No newline at end of file diff --git a/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/expected.json b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/expected.json new file mode 100644 index 00000000000..989bf407b47 --- /dev/null +++ b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/expected.json @@ -0,0 +1,5 @@ +{ _id: 1, flavor: 'chocolate' }, +{ _id: 2, flavor: 'strawberry' }, +{ _id: 3, flavor: 'cherry' }, +{ _id: 4, flavor: 'orange' }, +{ _id: 5, flavor: 'vanilla', price: 20 } \ No newline at end of file diff --git a/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/name b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/name new file mode 100644 index 00000000000..454b46d0b64 --- /dev/null +++ b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/name @@ -0,0 +1 @@ +Create a Union with Specified Documents \ No newline at end of file diff --git a/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/pipeline.json b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/pipeline.json new file mode 100644 index 00000000000..093e462734b --- /dev/null +++ b/core/src/test/resources/dev/morphia/test/aggregation/stages/unionWith/example3/pipeline.json @@ -0,0 +1,12 @@ +{ + $unionWith: { + pipeline: [ + { + $documents: [ + { _id: 4, flavor: "orange" }, + { _id: 5, flavor: "vanilla", price: 20 } + ] + } + ] + } + } \ No newline at end of file