Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you set boosts and filters with Laravel Scout and ElasticSearch?

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?

like image 954
ATLChris Avatar asked Sep 17 '16 00:09

ATLChris


2 Answers

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();
like image 52
Alexey Torochkov Avatar answered Oct 03 '22 20:10

Alexey Torochkov


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.

like image 32
ATLChris Avatar answered Oct 03 '22 19:10

ATLChris