Elasticsearch driver for Laravel Scout

Overview

Buy Me A Coffee


Elasticsearch driver for Laravel Scout.

Contents

Compatibility

The current version of Elastic Scout Driver has been tested with the following configuration:

  • PHP 7.2-8.0
  • Elasticsearch 7.0-7.10
  • Laravel 6.x-8.x
  • Laravel Scout 7.x-9.x

Installation

The library can be installed via Composer:

composer require babenkoivan/elastic-scout-driver

Note, that this library is just a driver for Laravel Scout, don't forget to install it beforehand:

composer require laravel/scout

After Scout has been installed, publish its configuration file using:

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

Then, change the driver option in the config/scout.php file to elastic:

// config/scout.php

'driver' => env('SCOUT_DRIVER', 'elastic'),

If you want to use Elastic Scout Driver with Lumen framework check this guide.

Configuration

Elastic Scout Driver uses babenkoivan/elastic-client as a dependency. If you want to change the default client settings (and I'm pretty sure you do), then you need to create the configuration file first:

php artisan vendor:publish --provider="ElasticClient\ServiceProvider"

You can change Elasticsearch host and the other client settings in the config/elastic.client.php file. Please refer to babenkoivan/elastic-client for more details.

Elastic Scout Driver itself has only one configuration option at the moment - refresh_documents. If it's set to true (false by default) documents are indexed immediately, which might be handy for testing.

You can configure refresh_documents in the config/elastic.scout_driver.php file after publishing it with the following command:

php artisan vendor:publish --provider="ElasticScoutDriver\ServiceProvider"

At last, do not forget, that with Scout you can configure the searchable data, the model id and the index name. Check the official Scout documentation for more details.

Note, that the _id field can't be part of the searchable data, so make sure the field is excluded or renamed in the toSearchableArray method in case you are using MongoDB as the database.

Basic usage

Elastic driver uses Elasticsearch query string wrapped in a bool query under the hood. It means that you can use mini-language syntax when searching a model:

$orders = App\Order::search('title:(Star OR Trek)')->get();

When the query string is omitted, the match all query is used:

$orders = App\Order::search()->where('user_id', 1)->get();

Please refer to the official Laravel Scout documentation for more details and usage examples.

Advanced Search

In case the basic search doesn't cover your project needs check Elastic Scout Driver Plus, which extends standard Scout search capabilities by introducing advanced query builders. These builders give you possibility to use compound queries, custom filters and sorting, highlights and more.

Migrations

If you are looking for a way to control Elasticsearch index schema programmatically check Elastic Migrations. Elastic Migrations allow you to modify application's index schema and share it across multiple environments with the same ease, that gives you Laravel database migrations.

Pitfalls

There are few things, which are slightly different from other Scout drivers:

  • As you probably know, Scout only indexes fields, which are returned by the toSearchableArray method. Elastic driver indexes a model even when toSearchableArray returns an empty array. You can change this behaviour by overwriting the shouldBeSearchable method of your model:
public function shouldBeSearchable()
{
    return count($this->toSearchableArray()) > 0;
}
  • Raw search returns an instance of SearchResponse class (see Elastic Adapter):
$searchResponse = App\Order::search('Star Trek')->raw();
  • To be compatible with other drivers and to not expose internal implementation of the engine, Elastic driver ignores callback parameter of the search method:
App\Order::search('Star Trek', function () {
    // this will not be triggered
})->get()
Comments
  • Import data eager loading relations

    Import data eager loading relations

    | Software | Version | --------------| --------------- | PHP | 7.3.22 | Elasticsearch | 7.9.2 | Laravel | 6.20.8 | Laravel Scout | 8.6.1

    Describe the bug When I try to use makeAllSearchableUsing function , I understand that this feature aims to eager load relations for mass indexing. If I test it without queue system, It works like a charm. But when I add queue system and try to load 10 millions rows it seems it does 30 millions sql queries. In fact it does not eager load relations anymore.

    I don't know if it is a scout bug, but I also reported it there : #https://github.com/laravel/scout/issues/462 In case I do things the right way, it is a major bug as the makeAllSearchableUsing feature is not usable for large set of data.

    @babenkoivan What do you think ?

    bug stale 
    opened by ybert 9
  • Rooting parameter for join functionality

    Rooting parameter for join functionality

    I'm trying to do a join by setting a parent/child relationship and I must set the rooting with the parent id in the URL to do it as explained in the documentation of ElasticSearch[1]. I've seen that ElasticAdapter only take body parameter before calling bulk function and no parameter is provided for rooting[2]. So is it possible to do it ? I can fork your work and try to resolve the problem by making a commit in few time if you want.

    [1] https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html [2] https://github.com/babenkoivan/elastic-adapter/blob/master/src/Documents/DocumentManager.php#L34

    feature 
    opened by luciegirard 8
  • feat: Do not call toSearchableArray when deleting models

    feat: Do not call toSearchableArray when deleting models

    When deleting models from search, we do not need to provide Elasticsearch with the full model data, just the "_id" field so that Elasticsearch knows which document to delete. Calling toSearchableArray on models that have been deleted from the database can cause issues if relations etc cannot be hydrated, and also creates an unnecessary database call. This commit adds an optional deleteMode argument to DocumentFactory. If this argument is true, then DocumentFactory no longer calls toSearchableArray on the models.

    opened by robtesch 7
  • Add support for custom es routing

    Add support for custom es routing

    Add a CustomRouting interface that exposes a getRoutingKey method to be implemented by developers. The routing key provided by this method is then provided to Documents and used in index and delete operations.

    This pr is linked to the elastic-adapter pr https://github.com/babenkoivan/elastic-adapter/pull/9 and we should first merge the latter. The changes on elastic-adapter should be backwards compatible and so no major version upgrade should be required.

    opened by spiritinlife 6
  • One or more operations in the bulk request did not complete successfully

    One or more operations in the bulk request did not complete successfully

    | Software | Version | --------------| --------------- | PHP | 7.4.19 | Elasticsearch | 7.10.0 | Laravel | 8.44.0 | Laravel Scout | 9.1.0

    Describe the bug Created a user record get the error: "One or more operations in the bulk request did not complete successfully" on saving

    To Reproduce Fresh docker image of elastic search 7.10 (cluster status: green - 3 nodes)

    php artisan scout:index user_index

    Current behavior Error when saving

    exception: "ElasticAdapter\\Exceptions\\BulkRequestException"
    file: "<-snip->/vendor/babenkoivan/elastic-adapter/src/Documents/DocumentManager.php"
    line: 51
    message: "One or more operations in the bulk request did not complete successfully"
    

    User model has trait Searchable and these methods:

      public function searchableAs()
       {
           return 'users_index';
       }
    
       public function toSearchableArray()
       {
           $array = $this->toArray();
    
           // Customize the data array...
    
           unset($array['password']);
           unset($array['remember_token']);
    
           return $array;
       }
    
    
       public function getScoutKey()
       {
           return $this->email;
       }
    
       public function getScoutKeyName()
       {
           return 'email';
       }
    

    Record hits db but doesn't end up in the ES index

    Expected behavior Expected save to be successful and record stored in both DB & ElasticSearch

    bug 
    opened by mbuk 5
  • Removing usage of `final` classes

    Removing usage of `final` classes

    Hi there!

    I'm wondering if you may accept a PR removing the final declarations? I'm unable to extend anything in this package (or the scout-driver-plus package) without copying and pasting the whole class over and binding onto the interface -- negating the benefits of having this package be open source and community supported, since I can't utilize any of their base methods.

    Is there a particular purpose for all classes to be final?

    Thanks for your time!

    feature 
    opened by stevebauman 5
  • Any plans on upgrading to ES8?

    Any plans on upgrading to ES8?

    Hey!

    Thanks for writing some really great software here.

    Just wondering if there are plans to upgrade to ES8? Will help me figure out if I need to write my own adapters or not as we are planning on upgrading.

    I havent tested with ES8 yet. Its quite possible that things still work. But thought Id reach out as a first step to get your thoughts.

    Cheers Lee

    feature stale 
    opened by leeovery 4
  • Add a way to do raw searches

    Add a way to do raw searches

    I need to make the following query but it appears as though I cannot do this in the base package.

                [
                    'multi_match' => [
                        'query' => $queryText,
                        'type' => 'cross_fields',
                        'operator' => 'and',
                        'fields' => ['*']
                    ],
                ];
    

    I am aware of the "plus" driver, but the builders generated by that package do not create Scout Builder interfaces that allow it to work with Nova.

    I have a fork in which I allowed array queries to be interpreted as raw searches and it appears to work fine for my use case.

    // SearchRequestFactory.php
        protected function makeQuery(Builder $builder): array
        {
            if (is_array($builder->query)) {
              return $builder->query;
            }
    
            $query = [
                'bool' => [],
            ];
    
            if (!empty($builder->query)) {
                $query['bool']['must'] = [
                    'query_string' => [
                        'query' => $builder->query,
                    ],
                ];
            } else {
                $query['bool']['must'] = [
                    'match_all' => new stdClass(),
                ];
            }
    
            if ($filter = $this->makeFilter($builder)) {
                $query['bool']['filter'] = $filter;
            }
    
            return $query;
        }
    
    feature 
    opened by swarley 4
  • Automatic index creation option

    Automatic index creation option

    Description

    Currently this scout driver throws an error when adding documents to an index that doesn't exist. By implementing this feature this elastic driver would create an empty index (without custom configuration) before populating it instead of throwing the error that the index doesn't exist. It would be fine to add a configuration option in the config/elastic.client.php that allows this.

    This comment https://github.com/babenkoivan/elastic-scout-driver/issues/5 suggests to use elastic migrations. But an automatic solution would - in my use case - be better. It would only need to create an empty index before populating it. I don't need any custom configuration for my indices. Adding an extra package isn't needed for me since that package is better suited for projects that need custom index configurations.

    Why

    In our use case we have multiple projects (with multiple environments per project) creating indices on the fly. On average we have 5 indices per project per environment (we have 3 environments per project, so 15 indices per project on average). Currently we need to manually setup each index before we can use it. It would be a lot simpler if this package would create them on the fly, since we do not need a custom configuration, instead of throwing an error if it doesn't exist.

    Also since other Laravel scout packages automatically create indices on the fly, it would therefore be logical that this package also does that since developers have a certain expectation of scout drivers.

    feature stale 
    opened by GijsGoudzwaard 4
  • No alive nodes locks entire app

    No alive nodes locks entire app

    I allow users to save events on my site. Everything works great unless the ES nodes go down. Then if a user tries to save something it sends back the error no alive nodes on your server and wont let them do anything. I figure this is how its supposed to work, but is there a way to allow the app to continue to save to the database even if the ES save doesn't work because the server is down?

    opened by chrisgrim 4
  • no result  push in elastic

    no result push in elastic

    | Software | Version | --------------| --------------- | PHP | 7.3.19 | Elasticsearch | 7.1.0 | Laravel | 6.* | Laravel Scout | 8.0

    Describe the bug hello , im using at mongodb from jenssegers/mongodb package .

    after run command : php artisan scout:import "App\product"

    show result : Imported [App\product] models up to ID: 5e35949da49f04517147be86 Imported [App\product] models up to ID: 5e35949da49f04517147c07c Imported [App\product] models up to ID: 5e35949ea49f04517147c277 . . . Imported [App\product] models up to ID: 5ee4ac112407e012ce3bed42 Imported [App\product] models up to ID: 5ee89e5588d2b237f6052402 Imported [App\product] models up to ID: 5eeb3ac95083517cc7581892 All [App\product] records have been imported

    but command : curl 'localhost:9200/_cat/indices?v'

    show result:

    health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open products RIuEwO2_T6SBIwJviIurBA 1 1 0 0 283b 283b

    ( docs.count = 0 ) :(

    my model :

    use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

    `class products extends Eloquent { use Searchable; protected $collection = 'products';

    public function shouldBeSearchable()
    {
        return count($this->toSearchableArray()) > 0;
    }
    
    public function toSearchableArray()
    {
        $array = $this->toArray();
    
        // Customize array...
    
        return $array;
    }
    

    }`

    scout driver :

    'driver' => env('SCOUT_DRIVER', 'elastic'),

    my code in web.php :

    Route::get('/', function () { $res = App\products::search('Asus')->get(); dd($res); });

    But show result :

    Illuminate\Database\Eloquent\Collection {#270 ▼ #items: [] }

    please help me :(

    bug 
    opened by Cloner311 4
Releases(v3.0.1)
Owner
Ivan Babenko
Ivan Babenko
Search among multiple models with ElasticSearch and Laravel Scout

For PHP8 support use php8 branch For Laravel Framework < 6.0.0 use 3.x branch The package provides the perfect starting point to integrate ElasticSear

Sergey Shlyakhov 592 Dec 25, 2022
Driver for Laravel Scout search package based on https://github.com/teamtnt/tntsearch

TNTSearch Driver for Laravel Scout - Laravel 5.3 - 8.0 This package makes it easy to add full text search support to your models with Laravel 5.3 to 8

TNT Studio 1k Dec 27, 2022
Laravel Scout provides a driver based solution to searching your Eloquent models.

Introduction Laravel Scout provides a simple, driver-based solution for adding full-text search to your Eloquent models. Once Scout is installed and c

The Laravel Framework 1.3k Dec 31, 2022
Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a fluent syntax for mapping, querying, and storing eloquent models.

Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a f

Sleiman Sleiman 511 Dec 31, 2022
A scout DB fulltext-based driver that store index data in related tables

A scout DB fulltext-based driver that store index data in related tables This package provide a Laravel/Scout Engine based on database/fulltext only,

Ivano Matteo 10 Nov 10, 2022
[Deprecated] We now recommend using Laravel Scout, see =>

[DEPRECATED] Algolia Search API Client for Laravel Algolia Search is a hosted full-text, numerical, and faceted search engine capable of delivering re

Algolia 240 Nov 25, 2022
Maps Laravel Eloquent models to Elasticsearch types

Elasticquent Elasticsearch for Eloquent Laravel Models Elasticquent makes working with Elasticsearch and Eloquent models easier by mapping them to Ela

Elasticquent 1.3k Jan 4, 2023
Elasticsearch migrations for Laravel

Elastic Migrations Elasticsearch migrations for Laravel allow you to easily modify and share indices schema across the application's environments. Con

Ivan Babenko 151 Dec 20, 2022
Laravel 8.* Elasticsearch Eloquent

Elasticsearch Installation composer require etsetra/elasticsearch Create config file $ php artisan vendor:publish --tag="etsetra-elasticsearch-config

Etsetra 2 Jan 14, 2022
Official PHP low-level client for Elasticsearch.

elasticsearch-php Official low-level client for Elasticsearch. Its goal is to provide common ground for all Elasticsearch-related code in PHP; because

elastic 5k Dec 31, 2022
Elastica is a PHP client for elasticsearch

Elastica: elasticsearch PHP Client All documentation for Elastica can be found under Elastica.io. If you have questions, don't hesitate to ask them on

Nicolas Ruflin 2.2k Dec 23, 2022
Store and retrieve objects from Algolia or Elasticsearch

Store and retrieve objects from a search index This is an opinionated Laravel 5.1 package to store and retrieve objects from a search index. Currently

Spatie 440 Dec 30, 2022
Build and execute an Elasticsearch search query using a fluent PHP API

PACKAGE IN DEVELOPMENT, DO NOT USE YET Build and execute ElasticSearch queries using a fluent PHP API This package is a lightweight query builder for

Spatie 94 Dec 14, 2022
This package offers advanced functionality for searching and filtering data in Elasticsearch.

Scout Elasticsearch Driver ?? Introducing a new Elasticsearch ecosystem for Laravel. ?? This package offers advanced functionality for searching and f

Ivan Babenko 1.2k Dec 20, 2022
Official PHP low-level client for Elasticsearch.

elasticsearch-php Official low-level client for Elasticsearch. Its goal is to provide common ground for all Elasticsearch-related code in PHP; because

elastic 5k Jan 1, 2023
This modules provides a Search API Backend for Elasticsearch.

Search API ElasticSearch This modules provides a Search API Backend for Elasticsearch. This module uses the official Elasticsearch PHP Client. Feature

null 1 Jan 20, 2022
Search products, categories, brands or tags with ElasticSearch

ElasticSearch for Shopaholic This plugin allows you to use ElasticSearch as search engine for Shopaholic. Benefits Easy to install, easy to use Opened

Biz-Mark 4 Feb 18, 2022
Query Builder for Elasticsearch

Query Builder for Elasticsearch

wangzhiqiang 5 Mar 2, 2022
The official SingleStore Laravel driver.

SingleStore Driver for Laravel This repository contains a SingleStore Driver for Laravel. Install You can install the package via composer: composer r

SingleStore Labs 197 Jan 1, 2023