I am building a search integration with Laravel Scout and Elasticsearch. I am trying to figure out how I can refine my queries for boosting.
Is it possible to do this with Laravel Scout or will I need to revert back to using the ElasticSearch PHP library directly?
Actually it can be simply done with custom Scout Engine.
Let's call it ElasticqueryEngine, for example, and extend it from default ElasticsearchEngine:
<?php
namespace App\Libs\Scout\Engines;
use Laravel\Scout\Builder;
use Laravel\Scout\Engines\ElasticsearchEngine;
class ElasticqueryEngine extends ElasticsearchEngine
{
/**
* Perform the given search on the engine.
*
* @param Builder $query
* @param array $options
* @return mixed
*/
protected function performSearch(Builder $query, array $options = [])
{
if (!is_array($query->query)) {
return parent::performSearch($query, $options);
}
$searchQuery = [
'index' => $this->index,
'type' => $query->model->searchableAs(),
'body' => [
'query' => $query->query,
],
];
if (array_key_exists('size', $options)) {
$searchQuery = array_merge($searchQuery, [
'size' => $options['size'],
]);
}
if (array_key_exists('from', $options)) {
$searchQuery = array_merge($searchQuery, [
'from' => $options['from'],
]);
}
return $this->elasticsearch->search($searchQuery);
}
}
Add new service provider to register new ElasticqueryEngine (or do it in any of the existing service providers):
<?php
namespace App\Providers;
use Laravel\Scout\EngineManager;
use Illuminate\Support\ServiceProvider;
use Elasticsearch\ClientBuilder as Elasticsearch;
use App\Libs\Scout\Engines\ElasticqueryEngine;
class ElasticqueryServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
resolve(EngineManager::class)->extend('elasticquery', function () {
return new ElasticqueryEngine(
Elasticsearch::fromConfig(config('scout.elasticsearch.config')),
config('scout.elasticsearch.index')
);
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
Don't forget to add new service provider in config/app.php:
'providers' => [
// ...
Laravel\Scout\ScoutServiceProvider::class,
App\Providers\ElasticqueryServiceProvider::class,
],
And change driver to "elasticquery" in config/scout.php or .env (SCOUT_DRIVER=elasticquery)
After all, you can search by any queries from https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html:
$query = [
'simple_query_string' => [
'query' => 'findme',
'fields' => [
'title^5',
'description',
],
],
];
$posts = Posts::search($query)->get();
// also you can use default ElasticsearchEngine query
$posts = Posts::search('findme')->where('user_id', 1)->get();
Laravel Scout does not support advanced Elasticsearch features. I ended up sticking with Scout for all of the index creation and updating based on model events, but I switched my search over to utilize the ElasticSearch library directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With