Skip to content

Commit 4f84a52

Browse files
authored
Merge branch 'master' into master
2 parents 40f7264 + 3d58b4b commit 4f84a52

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

src/Jenssegers/Mongodb/Query/Builder.php

+41-3
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@
88
use Illuminate\Database\Query\Expression;
99
use Illuminate\Support\Arr;
1010
use Illuminate\Support\Collection;
11+
use Illuminate\Support\LazyCollection;
1112
use Illuminate\Support\Str;
1213
use Jenssegers\Mongodb\Connection;
1314
use MongoDB\BSON\Binary;
1415
use MongoDB\BSON\ObjectID;
1516
use MongoDB\BSON\Regex;
1617
use MongoDB\BSON\UTCDateTime;
18+
use RuntimeException;
1719

20+
/**
21+
* Class Builder
22+
* @package Jenssegers\Mongodb\Query
23+
*/
1824
class Builder extends BaseBuilder
1925
{
2026
/**
@@ -208,12 +214,25 @@ public function get($columns = [])
208214
return $this->getFresh($columns);
209215
}
210216

217+
/**
218+
* @inheritdoc
219+
*/
220+
public function cursor($columns = [])
221+
{
222+
$result = $this->getFresh($columns, true);
223+
if ($result instanceof LazyCollection) {
224+
return $result;
225+
}
226+
throw new RuntimeException("Query not compatible with cursor");
227+
}
228+
211229
/**
212230
* Execute the query as a fresh "select" statement.
213231
* @param array $columns
214-
* @return array|static[]|Collection
232+
* @param bool $returnLazy
233+
* @return array|static[]|Collection|LazyCollection
215234
*/
216-
public function getFresh($columns = [])
235+
public function getFresh($columns = [], $returnLazy = false)
217236
{
218237
// If no columns have been specified for the select statement, we will set them
219238
// here to either the passed columns, or the standard default of retrieving
@@ -401,6 +420,14 @@ public function getFresh($columns = [])
401420
// Execute query and get MongoCursor
402421
$cursor = $this->collection->find($wheres, $options);
403422

423+
if ($returnLazy) {
424+
return LazyCollection::make(function () use ($cursor) {
425+
foreach ($cursor as $item) {
426+
yield $item;
427+
}
428+
});
429+
}
430+
404431
// Return results as an array with numeric keys
405432
$results = iterator_to_array($cursor, false);
406433
return $this->useCollections ? new Collection($results) : $results;
@@ -988,6 +1015,7 @@ protected function compileWhereAll(array $where)
9881015
protected function compileWhereBasic(array $where)
9891016
{
9901017
extract($where);
1018+
$is_numeric = false;
9911019

9921020
// Replace like or not like with a Regex instance.
9931021
if (in_array($operator, ['like', 'not like'])) {
@@ -999,15 +1027,21 @@ protected function compileWhereBasic(array $where)
9991027

10001028
// Convert to regular expression.
10011029
$regex = preg_replace('#(^|[^\\\])%#', '$1.*', preg_quote($value));
1030+
$plain_value = $value;
10021031

10031032
// Convert like to regular expression.
10041033
if (!Str::startsWith($value, '%')) {
10051034
$regex = '^' . $regex;
1035+
} else {
1036+
$plain_value = Str::replaceFirst('%', null, $plain_value);
10061037
}
10071038
if (!Str::endsWith($value, '%')) {
10081039
$regex .= '$';
1040+
} else {
1041+
$plain_value = Str::replaceLast('%', null, $plain_value);
10091042
}
10101043

1044+
$is_numeric = is_numeric($plain_value);
10111045
$value = new Regex($regex, 'i');
10121046
} // Manipulate regexp operations.
10131047
elseif (in_array($operator, ['regexp', 'not regexp', 'regex', 'not regex'])) {
@@ -1027,7 +1061,11 @@ protected function compileWhereBasic(array $where)
10271061
}
10281062

10291063
if (!isset($operator) || $operator == '=') {
1030-
$query = [$column => $value];
1064+
if ($is_numeric) {
1065+
$query = ['$where' => '/^'.$value->getPattern().'/.test(this.'.$column.')'];
1066+
} else {
1067+
$query = [$column => $value];
1068+
}
10311069
} elseif (array_key_exists($operator, $this->conversion)) {
10321070
$query = [$column => [$this->conversion[$operator] => $value]];
10331071
} else {

tests/QueryBuilderTest.php

+18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use Illuminate\Support\Facades\Date;
55
use Illuminate\Support\Facades\DB;
6+
use Illuminate\Support\LazyCollection;
67
use Jenssegers\Mongodb\Collection;
78
use Jenssegers\Mongodb\Query\Builder;
89
use MongoDB\BSON\ObjectId;
@@ -761,4 +762,21 @@ public function testHintOptions()
761762
$this->assertEquals('spork', $results[1]['name']);
762763
$this->assertEquals('fork', $results[0]['name']);
763764
}
765+
766+
public function testCursor()
767+
{
768+
$data = [
769+
['name' => 'fork', 'tags' => ['sharp', 'pointy']],
770+
['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
771+
['name' => 'spoon', 'tags' => ['round', 'bowl']],
772+
];
773+
DB::collection('items')->insert($data);
774+
775+
$results = DB::collection('items')->orderBy('_id', 'asc')->cursor();
776+
777+
$this->assertInstanceOf(LazyCollection::class, $results);
778+
foreach ($results as $i => $result) {
779+
$this->assertEquals($data[$i]['name'], $result['name']);
780+
}
781+
}
764782
}

tests/QueryTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ public function testLike(): void
6969

7070
$users = User::where('name', 'like', 't%')->get();
7171
$this->assertCount(1, $users);
72+
73+
$users = User::where('age', 'like', '%35%')->get();
74+
$this->assertCount(3, $users);
75+
76+
$users = User::where('age', 'like', '3%')->get();
77+
$this->assertCount(6, $users);
78+
79+
$users = User::where('age', 'like', '%3')->get();
80+
$this->assertCount(4, $users);
7281
}
7382

7483
public function testNotLike(): void

0 commit comments

Comments
 (0)