What is MeiliSearch?
As stated in their official website - MeiliSearch is an open source, blazingly fast and hyper relevant search-engine that will improve your search experience.
Laravel also supports MeiliSearch out of the box. Feel free to visit the documentation to know more about it: https://laravel.com/docs/8.x/scout#meilisearch
Install MeiliSearch on a Local Machine
Run the following command in your terminal to download and install meilisearch in your local machine.
curl -L https://install.meilisearch.com | sh
Then run the following command to start meilisearch in your terminal.
./meilisearch
Feel free to checkout their docs: https://docs.meilisearch.com/learn/getting_started/quick_start.html
Let's add some sample index. Your can download a sample books.json data from here:
https://gist.github.com/mithicher/cba0358aa205abc9795e33510a876aa6
Then open another terminal and run the following curl command:
curl \
-X POST 'http://127.0.0.1:7700/indexes/books/documents' \
--data @/Users/your-user-name/Downloads/books.json
Reusable Autocomplete Search Input
We will attempt to create a reusable search input component for MeiliSearch here by leveraging the power of Laravel's blade components, Alpine.js for a little javascript, and TailwindCSS for styling.
Install and Configure MeiliSearch With Laravel
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
Then updated your .env file with the credentials
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=meilisearch-master-key
MEILISEARCH_PRIVATE_KEY=meilisearch-private-key
MEILISEARCH_PUBLIC_KEY=meilisearch-public-key
To obtain public and private key from meilisearch run the following curl command:
curl -X GET 'http://127.0.0.1:7700/keys' \
--header "X-Meili-API-Key: your-master-key
Then go to config/scout.php and update this
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY', null),
'public_key' => env('MEILISEARCH_PUBLIC_KEY', null),
'private_key' => env('MEILISEARCH_PRIVATE_KEY', null),
]
Make sure to install the scout package via the following composer command
composer require laravel/scout
Assuming you have already configured alpine.js and tailwind css in your app.blade.php let us a create a blade component named meilisearch-autocomplete.blade.php inside your resources/views/components folder.
Full component can be found here:
https://gist.github.com/mithicher/76a551e0989df1b326ddbabf7f8edc21
Let's see how it works
<input
type="search"
autocomplete="off"
id="search"
name="search"
class="form-input bg-gray-50 focus:bg-white border-gray-200 mt-px pl-10 leading-none placeholder-gray-400 shadow-none rounded-lg flex-1 w-full transition duration-150 ease-in-out"
placeholder="{{ $placeholder }}"
x-model="searchString"
x-on:input.debounce.600ms="search()"
x-on:keydown.arrow-down.stop.prevent="highlightNext()"
x-on:keydown.arrow-up.stop.prevent="highlightPrevious()"
x-on:keydown.enter="goToLink()"
/>
We are adding a x-model that allows us to bind the value of an input element to an Alpine data. Then on every input with a delay of 600 milliseconds search() method is triggered.
<div
x-data="{
client: null,
host: '{{ $host }}',
apiKey: '{{ $publicKey }}',
state: '',
searchString: '',
results: {
hits: [],
}
async search() {
this.state = 'searching';
this.results = await this.client.index('{{ $indexName }}')
.search(this.searchString);
this.state = 'finished';
}
}"
x-init="client = new MeiliSearch({
host: host,
apiKey: apiKey
})"
x-cloak
class="relative"
>
...
</div>
As stated in the alpinejs.dev website:
Everything in Alpine starts with the x-data directive.
So we define an x-data along with some initial values. We then initialize the meilisearch client with the required credentials in the x-init directive and put in a local variable to reuse later.
async search() {
this.state = 'searching';
this.results = await this.client.index('{{ $indexName }}')
.search(this.searchString);
this.state = 'finished';
}
How to use it on our blade views
<x-meilisearch-autocomplete
placeholder="Search books..."
index-name="books"
public-key=""
host="http://127.0.0.1:7700/"
>
<a class="flex-1 flex" href="#">
<div class="w-24 h-32 rounded bg-gray-100 flex-shrink-0 mr-3 border">
<img :src="result.thumbnailUrl" alt="poster" loading="lazy" class="rounded w-full h-32 object-cover">
</div>
<div class="flex-1">
<div class="text-gray-800">
<p class="text-lg mb-1 font-medium leading-tight line-clamp-2" x-text="result.title"></p>
<p class="text-sm text-gray-500" x-text="result.authors.join(', ')"></p>
</div>
<div class="mt-2 flex space-x-2 items-center leading-none">
<div class="text-xs text-gray-500 truncate capitialize" x-text="result.categories.join(', ')"></div>
<div class="text-gray-400">•</div>
<div class="text-xs text-gray-500" x-text="result.isbn"></div>
<div class="text-gray-400">•</div>
<div class="text-xs text-gray-500" x-text="result.pageCount"></div>
</div>
<p class="text-xs mt-2 text-gray-500 line-clamp-3" x-text="result.shortDescription ? result.shortDescription.substr(0, 220) + '...' : result.shortDescription"></p>
</div>
</a>
</x-meilisearch-autocomplete>
So here we have a meilisearch blade component. Feel free to comment and any suggestion for improvement. I have skipped the keyboard navigation part but feel free to use the component and see.
Here are some resources that you should definitely check it out:
- https://statamic.com/addons/jrc9designstudio/meili-search
- https://chrisdicarlo.ca/blog/-alpinejs-and-livewire-autocomplete/
Follow me on twitter @mithicher and checkout my codepen https://codepen.io/mithicher.
See you next time. Bye 👋
Comments (0)