Skip to content

Commit 4d5d5dd

Browse files
committed
Refactor and improve #6
When performing a search apply withoutTrashed() filter only if index is "internal" (stored in model's table). Filter out all non-existing models when mapping search results to models.
1 parent 06e57be commit 4d5d5dd

File tree

2 files changed

+55
-17
lines changed

2 files changed

+55
-17
lines changed

src/PostgresEngine.php

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@ protected function performSearch(Builder $builder, $perPage = 0, $page = 1)
216216
// does not revceive a model instance
217217
$this->preserveModel($builder->model);
218218

219-
$indexColumn = $this->getIndexColumn($builder->model);
220-
221219
$bindings = collect([]);
222220

223221
// The choices of parser, dictionaries and which types of tokens to index are determined
@@ -228,6 +226,8 @@ protected function performSearch(Builder $builder, $perPage = 0, $page = 1)
228226
$bindings->push($this->searchConfig($builder->model) ?: null)
229227
->push($builder->query);
230228

229+
$indexColumn = $this->getIndexColumn($builder->model);
230+
231231
// Build the query
232232
$query = $this->database
233233
->table($builder->index ?: $builder->model->searchableAs())
@@ -238,21 +238,26 @@ protected function performSearch(Builder $builder, $perPage = 0, $page = 1)
238238
->whereRaw("$indexColumn @@ query")
239239
->orderBy('rank', 'desc')
240240
->orderBy($builder->model->getKeyName());
241-
//if model use soft delete - without trashed
242-
if (method_exists($builder->model, 'getDeletedAtColumn')) {
243-
$query->where($builder->model->getDeletedAtColumn(), null);
244-
}
245-
if ($perPage > 0) {
246-
$query->skip(($page - 1) * $perPage)
247-
->limit($perPage);
248-
}
249241

250242
// Transfer the where clauses that were set on the builder instance if any
251243
foreach ($builder->wheres as $key => $value) {
252244
$query->where($key, $value);
253245
$bindings->push($value);
254246
}
255247

248+
// If parsed documents are being stored in the model's table
249+
if (! $this->isExternalIndex($builder->model)) {
250+
// and the model uses soft deletes we need to exclude trashed rows
251+
if ($this->usesSoftDeletes($builder->model)) {
252+
$query->whereNull($builder->model->getDeletedAtColumn());
253+
}
254+
}
255+
256+
if ($perPage > 0) {
257+
$query->skip(($page - 1) * $perPage)
258+
->limit($perPage);
259+
}
260+
256261
return $this->database
257262
->select($query->toSql(), $bindings->all());
258263
}
@@ -277,7 +282,7 @@ public function mapIds($results)
277282
*
278283
* @param mixed $results
279284
* @param \Illuminate\Database\Eloquent\Model $model
280-
* @return Collection
285+
* @return \Illuminate\Support\Collection
281286
*/
282287
public function map($results, $model)
283288
{
@@ -293,9 +298,11 @@ public function map($results, $model)
293298
->get()
294299
->keyBy($model->getKeyName());
295300

296-
return $results->map(function ($result) use ($model, $models) {
297-
return $models[$result->{$model->getKeyName()}];
298-
});
301+
return $results->pluck($model->getKeyName())
302+
->intersect($models->keys()) // Filter out no longer existing models (i.e. soft deleted)
303+
->map(function ($key) use ($model, $models) {
304+
return $models[$key];
305+
});
299306
}
300307

301308
/**
@@ -490,4 +497,15 @@ protected function searchConfig(Model $model)
490497
{
491498
return $this->option($model, 'config', $this->config('config', ''));
492499
}
500+
501+
/**
502+
* Checks if the model uses the SoftDeletes trait.
503+
*
504+
* @param \Illuminate\Database\Eloquent\Model $model
505+
* @return bool
506+
*/
507+
protected function usesSoftDeletes(Model $model)
508+
{
509+
return method_exists($model, 'getDeletedAtColumn');
510+
}
493511
}

tests/PostgresEngineTest.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public function test_search_with_model_config()
154154
$engine->search($builder);
155155
}
156156

157-
public function test_search_with_soft_delete()
157+
public function test_search_with_soft_deletes()
158158
{
159159
list($engine, $db) = $this->getEngine();
160160

@@ -163,7 +163,7 @@ public function test_search_with_soft_delete()
163163
$table->shouldReceive('skip')->with(0)->andReturnSelf()
164164
->shouldReceive('limit')->with(5)->andReturnSelf()
165165
->shouldReceive('where')->with('bar', 1)->andReturnSelf()
166-
->shouldReceive('where')->with('deleted_at', null);
166+
->shouldReceive('whereNull')->with('deleted_at');
167167

168168
$db->shouldReceive('select')->with(null, [null, 'foo', 1]);
169169

@@ -173,7 +173,7 @@ public function test_search_with_soft_delete()
173173
$engine->search($builder);
174174
}
175175

176-
public function test_map_correctly_maps_results_to_models()
176+
public function test_maps_results_to_models()
177177
{
178178
list($engine) = $this->getEngine();
179179

@@ -188,6 +188,26 @@ public function test_map_correctly_maps_results_to_models()
188188
$this->assertCount(1, $results);
189189
}
190190

191+
public function test_map_filters_out_no_longer_existing_models()
192+
{
193+
list($engine) = $this->getEngine();
194+
195+
$model = Mockery::mock('StdClass');
196+
$model->shouldReceive('getKeyName')->andReturn('id');
197+
$model->shouldReceive('whereIn')->once()->with('id', [1, 2])->andReturn($model);
198+
199+
$expectedModel = new SoftDeletableTestModel();
200+
$expectedModel->id = 2;
201+
202+
$model->shouldReceive('get')->once()->andReturn(Collection::make([$expectedModel]));
203+
204+
$models = $engine->map(
205+
json_decode('[{"id": 1, "rank": 0.33, "total_count": 2}, {"id": 2, "rank": 0.31, "total_count": 2}]'), $model);
206+
207+
$this->assertCount(1, $models);
208+
$this->assertEquals(2, $models->first()->id);
209+
}
210+
191211
public function test_it_returns_total_count()
192212
{
193213
list($engine) = $this->getEngine();

0 commit comments

Comments
 (0)