Skip to content

Commit d726f05

Browse files
authored
Improve query and aggregator classes (doctrine#2702)
* Add joint iterable interface for queries and aggregations * Update declared return types for query and aggregation builders
1 parent f2f920e commit d726f05

File tree

5 files changed

+67
-9
lines changed

5 files changed

+67
-9
lines changed

lib/Doctrine/ODM/MongoDB/Aggregation/Aggregation.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@
77
use Doctrine\ODM\MongoDB\DocumentManager;
88
use Doctrine\ODM\MongoDB\Iterator\CachingIterator;
99
use Doctrine\ODM\MongoDB\Iterator\HydratingIterator;
10+
use Doctrine\ODM\MongoDB\Iterator\IterableResult;
1011
use Doctrine\ODM\MongoDB\Iterator\Iterator;
1112
use Doctrine\ODM\MongoDB\Iterator\UnrewindableIterator;
1213
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
1314
use Iterator as SPLIterator;
14-
use IteratorAggregate;
1515
use MongoDB\Collection;
1616
use MongoDB\Driver\CursorInterface;
1717

1818
use function array_merge;
1919
use function assert;
2020

2121
/** @phpstan-import-type PipelineExpression from Builder */
22-
final class Aggregation implements IteratorAggregate
22+
final class Aggregation implements IterableResult
2323
{
2424
/**
2525
* @param array<string, mixed> $pipeline
@@ -30,6 +30,26 @@ public function __construct(private DocumentManager $dm, private ?ClassMetadata
3030
{
3131
}
3232

33+
public function execute(): Iterator
34+
{
35+
return $this->getIterator();
36+
}
37+
38+
/**
39+
* Execute the query and return the first result.
40+
*
41+
* @return array<string, mixed>|object|null
42+
*/
43+
public function getSingleResult(): mixed
44+
{
45+
$clone = clone $this;
46+
47+
// Limit the pipeline to a single result for efficiency
48+
$this->pipeline[] = ['$limit' => 1];
49+
50+
return $clone->getIterator()->current() ?: null;
51+
}
52+
3353
public function getIterator(): Iterator
3454
{
3555
// Force cursor to be used

lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort;
88
use Doctrine\ODM\MongoDB\DocumentManager;
9+
use Doctrine\ODM\MongoDB\Iterator\IterableResult;
910
use Doctrine\ODM\MongoDB\Iterator\Iterator;
1011
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
1112
use Doctrine\ODM\MongoDB\Persisters\DocumentPersister;
@@ -246,8 +247,10 @@ public function geoNear($x, $y = null): Stage\GeoNear
246247
* Returns an aggregation object for the current pipeline
247248
*
248249
* @param array<string, mixed> $options
250+
*
251+
* @return Aggregation
249252
*/
250-
public function getAggregation(array $options = []): Aggregation
253+
public function getAggregation(array $options = []): IterableResult
251254
{
252255
$class = $this->hydrationClass ? $this->dm->getClassMetadata($this->hydrationClass) : null;
253256

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\ODM\MongoDB\Iterator;
6+
7+
use BadMethodCallException;
8+
use IteratorAggregate;
9+
10+
interface IterableResult extends IteratorAggregate
11+
{
12+
/**
13+
* Executes the operation and returns a result if available; null otherwise
14+
*/
15+
public function execute(): mixed;
16+
17+
/**
18+
* Executes the operation and returns a result iterator. If the operation
19+
* did not yield an iterator, this method will throw
20+
*
21+
* @throws BadMethodCallException if the operation did not yield an iterator.
22+
*/
23+
public function getIterator(): Iterator;
24+
25+
/**
26+
* Returns the first result only from the operation
27+
*
28+
* Note that the behaviour of fetching the first result is dependent on the
29+
* implementation. A separate operation might be involved.
30+
*/
31+
public function getSingleResult(): mixed;
32+
}

lib/Doctrine/ODM/MongoDB/Query/Builder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use BadMethodCallException;
88
use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort;
99
use Doctrine\ODM\MongoDB\DocumentManager;
10+
use Doctrine\ODM\MongoDB\Iterator\IterableResult;
1011
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
1112
use GeoJson\Geometry\Geometry;
1213
use GeoJson\Geometry\Point;
@@ -659,8 +660,10 @@ public function getNewObj(): array
659660
* Gets the Query executable.
660661
*
661662
* @param array<string, mixed> $options
663+
*
664+
* @return Query
662665
*/
663-
public function getQuery(array $options = []): Query
666+
public function getQuery(array $options = []): IterableResult
664667
{
665668
$documentPersister = $this->dm->getUnitOfWork()->getDocumentPersister($this->class->name);
666669

lib/Doctrine/ODM/MongoDB/Query/Query.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
use Doctrine\ODM\MongoDB\DocumentManager;
1010
use Doctrine\ODM\MongoDB\Iterator\CachingIterator;
1111
use Doctrine\ODM\MongoDB\Iterator\HydratingIterator;
12+
use Doctrine\ODM\MongoDB\Iterator\IterableResult;
1213
use Doctrine\ODM\MongoDB\Iterator\Iterator;
1314
use Doctrine\ODM\MongoDB\Iterator\PrimingIterator;
1415
use Doctrine\ODM\MongoDB\Iterator\UnrewindableIterator;
1516
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
1617
use Doctrine\ODM\MongoDB\MongoDBException;
1718
use Doctrine\ODM\MongoDB\UnitOfWork;
1819
use InvalidArgumentException;
19-
use IteratorAggregate;
2020
use MongoDB\Collection;
2121
use MongoDB\DeleteResult;
2222
use MongoDB\Driver\ReadPreference;
@@ -63,7 +63,7 @@
6363
* @phpstan-import-type Hints from UnitOfWork
6464
* @phpstan-import-type SortMeta from Sort
6565
*/
66-
final class Query implements IteratorAggregate
66+
final class Query implements IterableResult
6767
{
6868
public const TYPE_FIND = 1;
6969
public const TYPE_FIND_AND_UPDATE = 2;
@@ -200,7 +200,7 @@ public function debug(?string $name = null)
200200
*
201201
* @throws MongoDBException
202202
*/
203-
public function execute()
203+
public function execute(): mixed
204204
{
205205
$results = $this->runQuery();
206206

@@ -296,7 +296,7 @@ public function getQuery(): array
296296
*
297297
* @return array<string, mixed>|object|null
298298
*/
299-
public function getSingleResult()
299+
public function getSingleResult(): mixed
300300
{
301301
$clonedQuery = clone $this;
302302
$clonedQuery->query['limit'] = 1;
@@ -353,7 +353,7 @@ public function setRewindable(bool $rewindable = true): void
353353
/**
354354
* Execute the query and return its results as an array.
355355
*
356-
* @see IteratorAggregate::toArray()
356+
* @see Iterator::toArray()
357357
*
358358
* @return mixed[]
359359
*/

0 commit comments

Comments
 (0)