Skip to content

Commit

Permalink
✨ Introduce fuzzy search
Browse files Browse the repository at this point in the history
  • Loading branch information
marcreichel committed Oct 22, 2021
1 parent 5b8dc6e commit 2398386
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 2 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,27 @@ $games = Game::search('Fortnite')->get();

**Attention:** Searchable models are `Character`, `Collection`, `Game`, `Platform` and `Theme`.

#### Fuzzy Search ("where like" chain) (since v3.1.0)

```php
use MarcReichel\IGDBLaravel\Models\Game;

$games = Game::fuzzySearch(
// fields to search in
[
'name',
'involved_companies.company.name', // you can search for nested values as well
],
// the query to search for
'Call of Duty',
// enable/disable case sensitivity (disabled by default)
false,
)->get();
```

**Attention**: Keep in mind you have to do the sorting of the results yourself. They are not ordered by relevance or
something like this.

#### Where-Clauses

##### Simple Where Clauses
Expand Down
51 changes: 49 additions & 2 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,53 @@ public function search(string $query): self
return $this;
}

/**
* Add a fuzzy search to the query.
*
* @param mixed $key
* @param string $query
* @param bool $caseSensitive
* @param string $boolean
*
* @return self
* @throws ReflectionException
*/
public function fuzzySearch(
mixed $key,
string $query,
bool $caseSensitive = false,
string $boolean = '&',
): self {
$tokenizedQuery = explode(' ', $query);
$keys = collect($key)->crossJoin($tokenizedQuery)->toArray();

return $this->whereNested(function ($query) use ($keys, $caseSensitive) {
foreach($keys as $v) {
$query->whereLike($v[0], $v[1], $caseSensitive, '|');
}
}, $boolean);
}

/**
* Add an "or fuzzy search" to the query.
*
* @param mixed $key
* @param string $query
* @param bool $caseSensitive
* @param string $boolean
*
* @return self
* @throws ReflectionException
*/
public function orFuzzySearch(
mixed $key,
string $query,
bool $caseSensitive = false,
string $boolean = '|',
): self {
return $this->fuzzySearch($key, $query, $caseSensitive, $boolean);
}

/**
* Add a basic where clause to the query.
*
Expand Down Expand Up @@ -431,8 +478,8 @@ private function generateWhereLikeClause($key, $value, $caseSensitive, $operator
}

$operator = $caseSensitive ? $operator : $insensitiveOperator;
$prefix = $hasPrefix ? '*' : '';
$suffix = $hasSuffix ? '*' : '';
$prefix = $hasPrefix || !$hasSuffix ? '*' : '';
$suffix = $hasSuffix || !$hasPrefix ? '*' : '';
$value = json_encode($value, JSON_THROW_ON_ERROR);
$value = Str::start(Str::finish($value, $suffix), $prefix);

Expand Down
2 changes: 2 additions & 0 deletions src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
* @method static Builder skip(int $limit)
* @method static Builder forPage(int $page, int $perPage = 10)
* @method static Builder search(string $query)
* @method static Builder fuzzySearch(mixed $key, string $query, bool $caseSensitive = false, string $boolean = '&')
* @method static Builder orFuzzySearch(mixed $key, string $query, bool $caseSensitive = false, string $boolean = '|')
* @method static Builder where(mixed $key, mixed|null $operator = null, mixed|null $value = null, string $boolean = '&')
* @method static Builder orWhere(mixed $key, mixed|null $operator = null, mixed|null $value = null, string $boolean = '|')
* @method static Builder whereLike(string $key, string $value, bool $caseSensitive = true, string $boolean = '&')
Expand Down

0 comments on commit 2398386

Please sign in to comment.