Skip to content

Commit e038f34

Browse files
committed
fix: fixing search to use join instead of subquery
1 parent e5df1d4 commit e038f34

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

src/Filters/SearchableFilter.php

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,34 @@ public function filter(RestifyRequest $request, $query, $value)
2424
return $query;
2525
}
2626

27-
// This approach could be rewritten using join.
28-
collect($this->belongsToField->getSearchables())->each(function (string $attribute) use ($query, $likeOperator, $value) {
29-
$query->orWhere(
30-
$this->belongsToField->getRelatedModel($this->repository)::select($attribute)
31-
->whereColumn(
32-
$this->belongsToField->getQualifiedKey($this->repository),
33-
$this->belongsToField->getRelatedKey($this->repository)
34-
)
35-
->take(1),
36-
$likeOperator,
37-
"%{$value}%"
38-
);
27+
$relatedModel = $this->belongsToField->getRelatedModel($this->repository);
28+
$relatedTable = $relatedModel->getTable();
29+
$localKey = $this->belongsToField->getRelatedKey($this->repository);
30+
$foreignKey = $this->belongsToField->getQualifiedKey($this->repository);
31+
32+
// Check if we already joined this table
33+
$hasJoin = collect($query->getQuery()->joins ?? [])->contains(function ($join) use ($relatedTable, $localKey, $foreignKey) {
34+
return $join->table === $relatedTable
35+
&& collect($join->wheres)->contains(function ($where) use ($localKey, $foreignKey) {
36+
return isset($where['first']) && isset($where['second'])
37+
&& $where['first'] === $foreignKey
38+
&& $where['second'] === $localKey;
39+
});
40+
});
41+
42+
if (!$hasJoin) {
43+
$query->leftJoin($relatedTable, $foreignKey, '=', $localKey);
44+
}
45+
46+
// Apply search conditions using the joined table
47+
collect($this->belongsToField->getSearchables())->each(function (string $attribute) use ($query, $relatedTable, $likeOperator, $value) {
48+
$columnName = $relatedTable . '.' . $attribute;
49+
50+
if (! config('restify.search.case_sensitive')) {
51+
$query->orWhereRaw("UPPER({$columnName}) LIKE ?", ['%' . strtoupper($value) . '%']);
52+
} else {
53+
$query->orWhere($columnName, $likeOperator, "%{$value}%");
54+
}
3955
});
4056

4157
return $query;

src/Services/Search/RepositorySearchService.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,15 @@ public function prepareSearchFields(RestifyRequest $request, $query)
156156
);
157157

158158
$filter->filter($request, $query, $search);
159-
160-
$this->repository::collectRelated()
161-
->onlySearchable($request)
162-
->map(function (BelongsTo $field) {
163-
return SearchableFilter::make()->setRepository($this->repository)->usingBelongsTo($field);
164-
})
165-
->each(fn (SearchableFilter $filter) => $filter->filter($request, $query, $search));
166159
}
160+
161+
// Process related searchable fields
162+
$this->repository::collectRelated()
163+
->onlySearchable($request)
164+
->map(function (BelongsTo $field) {
165+
return SearchableFilter::make()->setRepository($this->repository)->usingBelongsTo($field);
166+
})
167+
->each(fn (SearchableFilter $filter) => $filter->filter($request, $query, $search));
167168
});
168169

169170
return $query;

0 commit comments

Comments
 (0)