diff --git a/generator/config/accumulator/concatArrays.yaml b/generator/config/accumulator/concatArrays.yaml new file mode 100644 index 000000000..baf61b5e3 --- /dev/null +++ b/generator/config/accumulator/concatArrays.yaml @@ -0,0 +1,30 @@ +# $schema: ../schema.json +name: $concatArrays +link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/concatArrays/' +type: + - accumulator + - window + - resolvesToArray +encode: single +description: | + Concatenates arrays to return the concatenated array. +arguments: + - + name: array + type: + - resolvesToArray # of arrays + variadic: array + description: | + An array of expressions that resolve to an array. + If any argument resolves to a value of null or refers to a field that is missing, `$concatArrays` returns `null`. +tests: + - + name: 'Warehouse collection' + link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/concatArrays/#example' + pipeline: + - + $project: + items: + $concatArrays: + - '$instock' + - '$ordered' diff --git a/generator/config/accumulator/setUnion.yaml b/generator/config/accumulator/setUnion.yaml new file mode 100644 index 000000000..8c8419f9e --- /dev/null +++ b/generator/config/accumulator/setUnion.yaml @@ -0,0 +1,32 @@ +# $schema: ../schema.json +name: $setUnion +link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/' +type: + - accumulator + - window + - resolvesToArray +encode: single +description: | + Takes two or more arrays and returns an array containing the elements that appear in any input array. +arguments: + - + name: array + type: + - resolvesToArray # of arrays + variadic: array + description: | + An array of expressions that resolve to an array. +tests: + - + name: 'Flowers collection' + link: 'https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/#example' + pipeline: + - + $project: + flowerFieldA: 1 + flowerFieldB: 1 + allValues: + $setUnion: + - "$flowerFieldA" + - "$flowerFieldB" + _id: 0 diff --git a/src/Builder/Accumulator/ConcatArraysAccumulator.php b/src/Builder/Accumulator/ConcatArraysAccumulator.php new file mode 100644 index 000000000..90ab96fa9 --- /dev/null +++ b/src/Builder/Accumulator/ConcatArraysAccumulator.php @@ -0,0 +1,57 @@ + 'array']; + + /** + * @var list $array An array of expressions that resolve to an array. + * If any argument resolves to a value of null or refers to a field that is missing, `$concatArrays` returns `null`. + */ + public readonly array $array; + + /** + * @param BSONArray|PackedArray|ResolvesToArray|array|string ...$array An array of expressions that resolve to an array. + * If any argument resolves to a value of null or refers to a field that is missing, `$concatArrays` returns `null`. + * @no-named-arguments + */ + public function __construct(PackedArray|ResolvesToArray|BSONArray|array|string ...$array) + { + if (\count($array) < 1) { + throw new InvalidArgumentException(\sprintf('Expected at least %d values for $array, got %d.', 1, \count($array))); + } + + if (! array_is_list($array)) { + throw new InvalidArgumentException('Expected $array arguments to be a list (array), named arguments are not supported'); + } + + $this->array = $array; + } +} diff --git a/src/Builder/Accumulator/FactoryTrait.php b/src/Builder/Accumulator/FactoryTrait.php index 9e9257549..486eb43a5 100644 --- a/src/Builder/Accumulator/FactoryTrait.php +++ b/src/Builder/Accumulator/FactoryTrait.php @@ -117,6 +117,20 @@ public static function bottomN( return new BottomNAccumulator($n, $sortBy, $output); } + /** + * Concatenates arrays to return the concatenated array. + * + * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/concatArrays/ + * @no-named-arguments + * @param BSONArray|PackedArray|ResolvesToArray|array|string ...$array An array of expressions that resolve to an array. + * If any argument resolves to a value of null or refers to a field that is missing, `$concatArrays` returns `null`. + */ + public static function concatArrays( + PackedArray|ResolvesToArray|BSONArray|array|string ...$array, + ): ConcatArraysAccumulator { + return new ConcatArraysAccumulator(...$array); + } + /** * Returns the number of documents in the group or window. * Distinct from the $count pipeline stage. @@ -453,6 +467,18 @@ public static function rank(): RankAccumulator return new RankAccumulator(); } + /** + * Takes two or more arrays and returns an array containing the elements that appear in any input array. + * + * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/ + * @no-named-arguments + * @param BSONArray|PackedArray|ResolvesToArray|array|string ...$array An array of expressions that resolve to an array. + */ + public static function setUnion(PackedArray|ResolvesToArray|BSONArray|array|string ...$array): SetUnionAccumulator + { + return new SetUnionAccumulator(...$array); + } + /** * Returns the value from an expression applied to a document in a specified position relative to the current document in the $setWindowFields stage partition. * New in MongoDB 5.0. diff --git a/src/Builder/Accumulator/SetUnionAccumulator.php b/src/Builder/Accumulator/SetUnionAccumulator.php new file mode 100644 index 000000000..e8ee446cc --- /dev/null +++ b/src/Builder/Accumulator/SetUnionAccumulator.php @@ -0,0 +1,53 @@ + 'array']; + + /** @var list $array An array of expressions that resolve to an array. */ + public readonly array $array; + + /** + * @param BSONArray|PackedArray|ResolvesToArray|array|string ...$array An array of expressions that resolve to an array. + * @no-named-arguments + */ + public function __construct(PackedArray|ResolvesToArray|BSONArray|array|string ...$array) + { + if (\count($array) < 1) { + throw new InvalidArgumentException(\sprintf('Expected at least %d values for $array, got %d.', 1, \count($array))); + } + + if (! array_is_list($array)) { + throw new InvalidArgumentException('Expected $array arguments to be a list (array), named arguments are not supported'); + } + + $this->array = $array; + } +} diff --git a/tests/Builder/Accumulator/ConcatArraysAccumulatorTest.php b/tests/Builder/Accumulator/ConcatArraysAccumulatorTest.php new file mode 100644 index 000000000..24d811d30 --- /dev/null +++ b/tests/Builder/Accumulator/ConcatArraysAccumulatorTest.php @@ -0,0 +1,33 @@ +assertSamePipeline(Pipelines::ConcatArraysWarehouseCollection, $pipeline); + } +} diff --git a/tests/Builder/Accumulator/Pipelines.php b/tests/Builder/Accumulator/Pipelines.php index fedc91ab4..23b313828 100644 --- a/tests/Builder/Accumulator/Pipelines.php +++ b/tests/Builder/Accumulator/Pipelines.php @@ -374,6 +374,26 @@ enum Pipelines: string ] JSON; + /** + * Warehouse collection + * + * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/concatArrays/#example + */ + case ConcatArraysWarehouseCollection = <<<'JSON' + [ + { + "$project": { + "items": { + "$concatArrays": [ + "$instock", + "$ordered" + ] + } + } + } + ] + JSON; + /** * Use in $group Stage * @@ -1913,6 +1933,35 @@ enum Pipelines: string ] JSON; + /** + * Flowers collection + * + * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/#example + */ + case SetUnionFlowersCollection = <<<'JSON' + [ + { + "$project": { + "flowerFieldA": { + "$numberInt": "1" + }, + "flowerFieldB": { + "$numberInt": "1" + }, + "allValues": { + "$setUnion": [ + "$flowerFieldA", + "$flowerFieldB" + ] + }, + "_id": { + "$numberInt": "0" + } + } + } + ] + JSON; + /** * Shift Using a Positive Integer * diff --git a/tests/Builder/Accumulator/SetUnionAccumulatorTest.php b/tests/Builder/Accumulator/SetUnionAccumulatorTest.php new file mode 100644 index 000000000..a6b83c5c2 --- /dev/null +++ b/tests/Builder/Accumulator/SetUnionAccumulatorTest.php @@ -0,0 +1,36 @@ +assertSamePipeline(Pipelines::SetUnionFlowersCollection, $pipeline); + } +} diff --git a/tests/drivers-evergreen-tools b/tests/drivers-evergreen-tools index 147364aa4..92e5f9336 160000 --- a/tests/drivers-evergreen-tools +++ b/tests/drivers-evergreen-tools @@ -1 +1 @@ -Subproject commit 147364aa42c825a6176a5b5f43c1eff4af24b2bd +Subproject commit 92e5f93363ed12e91f1ef95a42575f47621365c8 diff --git a/tests/specifications b/tests/specifications index db693517d..4e5d62456 160000 --- a/tests/specifications +++ b/tests/specifications @@ -1 +1 @@ -Subproject commit db693517de561465621b474558ded99eaf38757d +Subproject commit 4e5d6245655f30f13e42a15bd340f57f6729bb27