Skip to content

Commit 697c36f

Browse files
authored
PHPORM-209 Add query builder helper to set read preference (#3244)
* PHPORM-209 Add query builder helper to set read preference * Support query timeout as decimal number of seconds
1 parent 8829052 commit 697c36f

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

Diff for: src/Query/Builder.php

+28-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use MongoDB\Builder\Type\QueryInterface;
2929
use MongoDB\Builder\Type\SearchOperatorInterface;
3030
use MongoDB\Driver\Cursor;
31+
use MongoDB\Driver\ReadPreference;
3132
use Override;
3233
use RuntimeException;
3334
use stdClass;
@@ -102,7 +103,7 @@ class Builder extends BaseBuilder
102103
/**
103104
* The maximum amount of seconds to allow the query to run.
104105
*
105-
* @var int
106+
* @var int|float
106107
*/
107108
public $timeout;
108109

@@ -113,6 +114,8 @@ class Builder extends BaseBuilder
113114
*/
114115
public $hint;
115116

117+
private ReadPreference $readPreference;
118+
116119
/**
117120
* Custom options to add to the query.
118121
*
@@ -211,7 +214,7 @@ public function project($columns)
211214
/**
212215
* The maximum amount of seconds to allow the query to run.
213216
*
214-
* @param int $seconds
217+
* @param int|float $seconds
215218
*
216219
* @return $this
217220
*/
@@ -454,7 +457,7 @@ public function toMql(): array
454457

455458
// Apply order, offset, limit and projection
456459
if ($this->timeout) {
457-
$options['maxTimeMS'] = $this->timeout * 1000;
460+
$options['maxTimeMS'] = (int) ($this->timeout * 1000);
458461
}
459462

460463
if ($this->orders) {
@@ -1534,6 +1537,24 @@ public function options(array $options)
15341537
return $this;
15351538
}
15361539

1540+
/**
1541+
* Set the read preference for the query
1542+
*
1543+
* @see https://www.php.net/manual/en/class.mongodb-driver-readpreference.php
1544+
*
1545+
* @param string $mode
1546+
* @param array $tagSets
1547+
* @param array $options
1548+
*
1549+
* @return $this
1550+
*/
1551+
public function readPreference(string $mode, ?array $tagSets = null, ?array $options = null): static
1552+
{
1553+
$this->readPreference = new ReadPreference($mode, $tagSets, $options);
1554+
1555+
return $this;
1556+
}
1557+
15371558
/**
15381559
* Performs a full-text search of the field or fields in an Atlas collection.
15391560
* NOTE: $search is only available for MongoDB Atlas clusters, and is not available for self-managed deployments.
@@ -1642,6 +1663,10 @@ private function inheritConnectionOptions(array $options = []): array
16421663
}
16431664
}
16441665

1666+
if (! isset($options['readPreference']) && isset($this->readPreference)) {
1667+
$options['readPreference'] = $this->readPreference;
1668+
}
1669+
16451670
return $options;
16461671
}
16471672

Diff for: tests/Query/BuilderTest.php

+26
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Mockery as m;
1616
use MongoDB\BSON\Regex;
1717
use MongoDB\BSON\UTCDateTime;
18+
use MongoDB\Driver\ReadPreference;
1819
use MongoDB\Laravel\Connection;
1920
use MongoDB\Laravel\Query\Builder;
2021
use MongoDB\Laravel\Query\Grammar;
@@ -1416,6 +1417,31 @@ function (Builder $elemMatchQuery): void {
14161417
['find' => [['embedded._id' => 1], []]],
14171418
fn (Builder $builder) => $builder->where('embedded->id', 1),
14181419
];
1420+
1421+
yield 'options' => [
1422+
['find' => [[], ['comment' => 'hello']]],
1423+
fn (Builder $builder) => $builder->options(['comment' => 'hello']),
1424+
];
1425+
1426+
yield 'readPreference' => [
1427+
['find' => [[], ['readPreference' => new ReadPreference(ReadPreference::SECONDARY_PREFERRED)]]],
1428+
fn (Builder $builder) => $builder->readPreference(ReadPreference::SECONDARY_PREFERRED),
1429+
];
1430+
1431+
yield 'readPreference advanced' => [
1432+
['find' => [[], ['readPreference' => new ReadPreference(ReadPreference::NEAREST, [['dc' => 'ny']], ['maxStalenessSeconds' => 120])]]],
1433+
fn (Builder $builder) => $builder->readPreference(ReadPreference::NEAREST, [['dc' => 'ny']], ['maxStalenessSeconds' => 120]),
1434+
];
1435+
1436+
yield 'hint' => [
1437+
['find' => [[], ['hint' => ['foo' => 1]]]],
1438+
fn (Builder $builder) => $builder->hint(['foo' => 1]),
1439+
];
1440+
1441+
yield 'timeout' => [
1442+
['find' => [[], ['maxTimeMS' => 2345]]],
1443+
fn (Builder $builder) => $builder->timeout(2.3456),
1444+
];
14191445
}
14201446

14211447
#[DataProvider('provideExceptions')]

0 commit comments

Comments
 (0)