#database #development #laravel #php
When you use Laravel Scout for full-text search, you can change the way it finds the results by using a proper matching strategy. In this post, I'll show you how to do that.
I'm assuming you are using Meilisearch in as your full-text search engine. When you use a different engine, this trick will not work.
The matching strategies
Meilisearch has two matching strategies:
-
last
(the default): returns documents containing all the query terms first. If there are not enough results containing all query terms to meet the requestedlimit
, Meilisearch will remove one query term at a time, starting from the end of the query.When you for example search for "big fat liar", Meilisearch will first return documents that contain all three words. If the results don't meet the requested limit, it will also return documents containing only the first two terms, big fat, followed by documents containing only big.
-
all
: only returns documents that contain all query terms. Meilisearch will not match any more documents even if there aren't enough to meet the requestedlimit
.When you for example search for "big fat liar", it would only return documents containing all three words.
Search setup
First, let's look at how the model we're using is setup. In my use-case, I'm having a Document
class which contains
both a searchable field name
(the name of the document) and text
(the actual text contents of the file).
To achieve, this, I've setup the following model:
app/Models/Document.php
namespace App\\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
final class Document extends Model
{
use Searchable;
public function searchableAs(): string
{
return 'documents_index';
}
public function toSearchableArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'text' => $this->text,
];
}
}
In my Laravel scout configuration, I marked all of these attributes as searchable:
config/scout.php
return [
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY', null),
'index-settings' => [
Document::class => [
'filterableAttributes'=> ['id', 'name', 'text'],
'sortableAttributes' => [],
],
],
],
];
After configuring the search, don't forget to sync the index settings before you start adding items to the index (as described here):
php artisan scout:sync-index-settings
Specifying the matching strategy
I want to be able to search on both fields, it's simply doing:
use App\\Models\\Document;
Document::search($query)->get();
This will use the default matching strategy from Meilisearch.
To specify a different matching strategy, you can do the following:
use App\\Models\\Document;
use Meilisearch\Endpoints\Indexes;
Document::search(
$searchQuery,
function (Indexes $searchEngine, string $query, array $options) {
$options['matchingStrategy'] = 'all';
return $searchEngine->search($query, $options);
}
)->get();
The function you specify in the search function allows you to customize the search
options for this query. In this example, we used the
option matchingStrategy
to specify the
attributes we want to search on.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.