Skip to content

Commit a6e2923

Browse files
committed
Factorize map/lazyMap
1 parent bd218ac commit a6e2923

File tree

3 files changed

+72
-71
lines changed

3 files changed

+72
-71
lines changed

Diff for: src/Scout/ScoutEngine.php

+50-69
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
use function array_column;
2929
use function array_flip;
30-
use function array_key_exists;
3130
use function array_map;
3231
use function array_merge;
3332
use function assert;
@@ -44,7 +43,6 @@
4443
use function method_exists;
4544
use function sleep;
4645
use function sprintf;
47-
use function substr;
4846
use function time;
4947

5048
/**
@@ -313,40 +311,67 @@ public function mapIds($results): Collection
313311
*
314312
* @see Engine::map()
315313
*
316-
* @param array $results
317-
* @param Model $model
314+
* @param Builder $builder
315+
* @param array|Cursor $results
316+
* @param Model $model
317+
*
318+
* @return Collection
318319
*/
319320
#[Override]
320321
public function map(Builder $builder, $results, $model): Collection
321322
{
322-
assert(is_array($results), new TypeError(sprintf('Argument #2 ($results) must be of type array, %s given', get_debug_type($results))));
323-
assert($model instanceof Model, new TypeError(sprintf('Argument #3 ($model) must be of type %s, %s given', Model::class, get_debug_type($model))));
323+
return $this->doMap($builder, $results, $model, false);
324+
}
325+
326+
/**
327+
* Map the given results to instances of the given model via a lazy collection.
328+
*
329+
* @see Engine::lazyMap()
330+
*
331+
* @param Builder $builder
332+
* @param array|Cursor $results
333+
* @param Model $model
334+
*
335+
* @return LazyCollection
336+
*/
337+
#[Override]
338+
public function lazyMap(Builder $builder, $results, $model): LazyCollection
339+
{
340+
return $this->doMap($builder, $results, $model, true);
341+
}
324342

343+
/** @return ($lazy is true ? LazyCollection : Collection)<mixed> */
344+
private function doMap(Builder $builder, array $results, Model $model, bool $lazy): Collection|LazyCollection
345+
{
325346
if (! $results) {
326-
return $model->newCollection();
347+
$collection = $model->newCollection();
348+
349+
return $lazy ? LazyCollection::make($collection) : $collection;
327350
}
328351

329352
$objectIds = array_column($results, '_id');
330353
$objectIdPositions = array_flip($objectIds);
331354

332-
return $model->getScoutModelsByIds(
333-
$builder,
334-
$objectIds,
335-
)->filter(function ($model) use ($objectIdPositions) {
336-
return array_key_exists($model->getScoutKey(), $objectIdPositions);
337-
})->map(function ($model) use ($results, $objectIdPositions) {
338-
$result = $results[$objectIdPositions[$model->getScoutKey()]] ?? [];
339-
340-
foreach ($result as $key => $value) {
341-
if ($key[0] === '_') {
342-
$model->withScoutMetadata($key, $value);
355+
return $model->queryScoutModelsByIds($builder, $objectIds)
356+
->{$lazy ? 'cursor' : 'get'}()
357+
->filter(function ($model) use ($objectIds) {
358+
return in_array($model->getScoutKey(), $objectIds);
359+
})
360+
->map(function ($model) use ($results, $objectIdPositions) {
361+
$result = $results[$objectIdPositions[$model->getScoutKey()]] ?? [];
362+
363+
foreach ($result as $key => $value) {
364+
if ($key[0] === '_' && $key !== '_id') {
365+
$model->withScoutMetadata($key, $value);
366+
}
343367
}
344-
}
345368

346-
return $model;
347-
})->sortBy(function ($model) use ($objectIdPositions) {
348-
return $objectIdPositions[$model->getScoutKey()];
349-
})->values();
369+
return $model;
370+
})
371+
->sortBy(function ($model) use ($objectIdPositions) {
372+
return $objectIdPositions[$model->getScoutKey()];
373+
})
374+
->values();
350375
}
351376

352377
/**
@@ -364,7 +389,7 @@ public function getTotalCount($results): int
364389
return 0;
365390
}
366391

367-
return $results[0]['__count'];
392+
return $results[0]->__count;
368393
}
369394

370395
/**
@@ -384,50 +409,6 @@ public function flush($model): void
384409
$collection->deleteMany([]);
385410
}
386411

387-
/**
388-
* Map the given results to instances of the given model via a lazy collection.
389-
*
390-
* @see Engine::lazyMap()
391-
*
392-
* @param Builder $builder
393-
* @param array|Cursor $results
394-
* @param Model $model
395-
*
396-
* @return LazyCollection
397-
*/
398-
#[Override]
399-
public function lazyMap(Builder $builder, $results, $model): LazyCollection
400-
{
401-
assert($results instanceof Cursor || is_array($results), new TypeError(sprintf('Argument #2 ($results) must be of type %s|array, %s given', Cursor::class, get_debug_type($results))));
402-
assert($model instanceof Model, new TypeError(sprintf('Argument #3 ($model) must be of type %s, %s given', Model::class, get_debug_type($model))));
403-
404-
if (! $results) {
405-
return LazyCollection::make($model->newCollection());
406-
}
407-
408-
$objectIds = array_column($results, '_id');
409-
$objectIdPositions = array_flip($objectIds);
410-
411-
return $model->queryScoutModelsByIds(
412-
$builder,
413-
$objectIds,
414-
)->cursor()->filter(function ($model) use ($objectIds) {
415-
return in_array($model->getScoutKey(), $objectIds);
416-
})->map(function ($model) use ($results, $objectIdPositions) {
417-
$result = $results[$objectIdPositions[$model->getScoutKey()]] ?? [];
418-
419-
foreach ($result as $key => $value) {
420-
if (substr($key, 0, 1) === '_') {
421-
$model->withScoutMetadata($key, $value);
422-
}
423-
}
424-
425-
return $model;
426-
})->sortBy(function ($model) use ($objectIdPositions) {
427-
return $objectIdPositions[$model->getScoutKey()];
428-
})->values();
429-
}
430-
431412
/**
432413
* Create the MongoDB Atlas Search index.
433414
*
@@ -475,7 +456,7 @@ public function deleteIndex($name): void
475456
{
476457
assert(is_string($name), new TypeError(sprintf('Argument #1 ($name) must be of type string, %s given', get_debug_type($name))));
477458

478-
$this->database->selectCollection($name)->drop();
459+
$this->database->dropCollection($name);
479460
}
480461

481462
/** Get the MongoDB collection used to search for the provided model */

Diff for: tests/Scout/ScoutEngineTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,11 @@ public function testPaginate()
403403
}
404404

405405
#[DataProvider('provideResultsForMapIds')]
406-
public function testMapIds(array $results): void
406+
public function testLazyMapIds(array $results): void
407407
{
408408
$engine = new ScoutEngine(m::mock(Database::class), softDelete: false);
409409

410-
$ids = $engine->mapIds($results);
410+
$ids = $engine->lazyMap($results);
411411

412412
$this->assertInstanceOf(IlluminateCollection::class, $ids);
413413
$this->assertEquals(['key_1', 'key_2'], $ids->all());

Diff for: tests/Scout/ScoutIntegrationTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,26 @@ public function testItCanUseBasicSearch()
145145
], $results->pluck('name', 'id')->all());
146146
}
147147

148+
#[Depends('testItCanCreateTheCollection')]
149+
public function testItCanUseBasicSearchCursor()
150+
{
151+
// All the search queries use "sort" option to ensure the results are deterministic
152+
$results = ScoutUser::search('lar')->take(10)->orderBy('id')->cursor();
153+
154+
self::assertSame([
155+
1 => 'Laravel Framework',
156+
11 => 'Larry Casper',
157+
12 => 'Reta Larkin',
158+
20 => 'Prof. Larry Prosacco DVM',
159+
39 => 'Linkwood Larkin',
160+
40 => 'Otis Larson MD',
161+
41 => 'Gudrun Larkin',
162+
42 => 'Dax Larkin',
163+
43 => 'Dana Larson Sr.',
164+
44 => 'Amos Larson Sr.',
165+
], $results->pluck('name', 'id')->all());
166+
}
167+
148168
#[Depends('testItCanCreateTheCollection')]
149169
public function testItCanUseBasicSearchWithQueryCallback()
150170
{

0 commit comments

Comments
 (0)