Skip to content

PHPORM-221 Convert $near into $geoWithin for count used by pagination #3073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
* Add `Query\Builder::incrementEach()` and `decrementEach()` methods by @SmallRuralDog in [#2550](https://github.com/mongodb/laravel-mongodb/pull/2550)
* Deprecate `Connection::collection()` and `Schema\Builder::collection()` methods by @GromNaN in [#3062](https://github.com/mongodb/laravel-mongodb/pull/3062)
* Deprecate `Model::$collection` property to customize collection name. Use `$table` instead by @GromNaN in [#3064](https://github.com/mongodb/laravel-mongodb/pull/3064)
* Convert `$near` to `$geoWithin` in queries using aggregation by @GromNaN in [#3073](https://github.com/mongodb/laravel-mongodb/pull/3073)

## [4.7.0] - 2024-07-19

Expand Down
19 changes: 16 additions & 3 deletions src/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,9 @@ public function toMql(): array
$columns = [];
}

$wheres = $this->compileWheres();

// Use MongoDB's aggregation framework when using grouping or aggregation functions.
if ($this->groups || $this->aggregate) {
$wheres = $this->compileWheres(true);
$group = [];
$unwinds = [];

Expand Down Expand Up @@ -404,6 +403,8 @@ public function toMql(): array
return ['aggregate' => [$pipeline, $options]];
}

$wheres = $this->compileWheres();

// Distinct query
if ($this->distinct) {
// Return distinct results directly
Expand Down Expand Up @@ -1133,7 +1134,7 @@ public function where($column, $operator = null, $value = null, $boolean = 'and'
*
* @return array
*/
protected function compileWheres(): array
protected function compileWheres(bool $aggregation = false): array
{
// The wheres to compile.
$wheres = $this->wheres ?: [];
Expand All @@ -1150,6 +1151,18 @@ protected function compileWheres(): array
if (isset($this->conversion[$where['operator']])) {
$where['operator'] = $this->conversion[$where['operator']];
}

// Convert $near to $geoWithin for aggregations
if ($aggregation && $where['operator'] === 'near' && isset($where['value']['$geometry']) && isset($where['value']['$maxDistance'])) {
$where['operator'] = 'geoWithin';
$where['value'] = [
'$centerSphere' => [
$where['value']['$geometry']['coordinates'],
// Convert meters to radians
$where['value']['$maxDistance'] / 6378100,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$minDistance is missing

],
];
}
}

// Convert column name to string to use as array key
Expand Down
29 changes: 28 additions & 1 deletion tests/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use BadMethodCallException;
use DateTimeImmutable;
use Illuminate\Support\Facades\Schema;
use LogicException;
use MongoDB\BSON\Regex;
use MongoDB\Laravel\Eloquent\Builder;
Expand Down Expand Up @@ -44,7 +45,9 @@ public function setUp(): void

public function tearDown(): void
{
User::truncate();
Schema::table('users', function ($table) {
$table->drop();
});
Scoped::truncate();
Birthday::truncate();

Expand Down Expand Up @@ -574,6 +577,30 @@ public function testPaginateDistinct(): void
User::distinct('age')->paginate(2);
}

public function testPaginateNear(): void
{
Schema::table('users', function ($table) {
$table->geospatial('position', '2dsphere');
});
User::insert([
['name' => 'Store A', 'position' => [9.224596977233887, 52.03082275390625]],
['name' => 'Store B', 'position' => [9.224596977233887, 52.03082275390625]],
['name' => 'Store C', 'position' => [9.3731451034548, 52.10194]],
]);

$query = User::where('position', 'near', [
'$geometry' => [
'type' => 'Point',
'coordinates' => [9.3731451034546, 52.1019308],
],
'$maxDistance' => 50,
]);
$result = $query->paginate();

$this->assertCount(1, $result->items());
$this->assertSame('Store C', $result->first()->name);
}

public function testUpdate(): void
{
$this->assertEquals(1, User::where(['name' => 'John Doe'])->update(['name' => 'Jim Morrison']));
Expand Down
Loading