Store and retrieve objects from Algolia or Elasticsearch

Related tags

Search searchindex
Overview

Store and retrieve objects from a search index

Latest Version Software License Build status Quality Score StyleCI Total Downloads

This is an opinionated Laravel 5.1 package to store and retrieve objects from a search index. Currently Elasticsearch and Algolia are supported.

Once the package is installed objects can be easily indexed and retrieved:

//$product is an object that implements the Searchable interface
SearchIndex::upsertToIndex($product);

SearchIndex::getResults('look for this');

Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Postcardware

You're free to use this package (it's MIT-licensed), but if it makes it to your production environment you are required to send us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.

The best postcards will get published on the open source page on our website.

Installation

This package can be installed through Composer.

composer require spatie/searchindex

You must install this service provider.

// config/app.php
'providers' => [
    ...
    Spatie\SearchIndex\SearchIndexServiceProvider::class,
];

This package also comes with a facade, which provides an easy way to call the the class.

// config/app.php
'aliases' => [
	...
	'SearchIndex' => Spatie\SearchIndex\SearchIndexFacade::class,
]

You can publish the config-file with:

php artisan vendor:publish --provider="Spatie\SearchIndex\SearchIndexServiceProvider"

The options in the config file are set with sane default values and they should be self-explanatory.

The next installation steps depend on if you want to use Elasticsearch or Algolia.

Elasticsearch

To use Elasticsearch you must install the official 1.x series low level client:

composer require elasticsearch/elasticsearch "^1.3"

You also should have a server with Elasticsearch installed. If you want to install it on your local development machine you can use these instructions from the excellent Vaprobash repo.

Algolia

To use Algolia you must install the official low level client:

composer require algolia/algoliasearch-client-php

Usage

Prepare your object

Objects that you want to store in the index should implement the provided Spatie\SearchIndex\Searchable- interface.

namespace Spatie\SearchIndex;

interface Searchable {

    /**
     * Returns an array with properties which must be indexed
     *
     * @return array
     */
    public function getSearchableBody();

    /**
     * Return the type of the searchable subject
     *
     * @return string
     */
    public function getSearchableType();

    /**
     * Return the id of the searchable subject
     *
     * @return string
     */
    public function getSearchableId();

Here is an example how you could implement it with an Eloquent model:

class Product extends Eloquent implements Searchable
{
    
    ...
    
    /**
     * Returns an array with properties which must be indexed
     *
     * @return array
     */
    public function getSearchableBody()
    {
        $searchableProperties = [
            'name' => $this->name,
            'brand' => $this->brand->name,
            'category' => $this->category->name
        ];
        
        return $searchableProperties;

    }

    /**
     * Return the type of the searchable subject
     *
     * @return string
     */
    public function getSearchableType()
    {
        return 'product';
    }

    /**
     * Return the id of the searchable subject
     *
     * @return string
     */
    public function getSearchableId()
    {
        return $this->id;
    }
}

The searchindex will use the returned searchableType and searchableId to identify an object in the index.

Add an object to the index

If you are using the facade it couldn't be simpler.

//$product is an object that implements the Searchable interface

SearchIndex::upsertToIndex($product);

Update an object in the index

You probably would have guessed it.

//$product is an object that implements the Searchable interface

SearchIndex::upsertToIndex($product);

Remove an object from the index

Yep. Easy.

//$product is an object that implements the Searchable interface

SearchIndex::removeFromIndex($product);

Alternatively you can remove an object from the index by passing type and id:

SearchIndex::removeFromIndexByTypeAndId('product', 1);

This can be handy when you've already deleted your model.

Clear the entire index

If only you could to this with your facebook account.

SearchIndex::clearIndex();

Perform a search on the index

You can retrieve search results with this method:

SearchIndex::getResults($query);

Elasticsearch

$query should be an array that adheres to the scheme provided by the elasticsearch documentation.

A query to perform a fuzzy like search that operates all fields of the index could look like this:

$query =
    [
        'body' =>
            [
                'from' => 0,
                'size' => 500,
                'query' =>
                    [
                        'fuzzy_like_this' =>
                            [
                                '_all' =>
                                    [
                                        'like_text' => 'look for this',
                                        'fuzziness' => 0.5,
                                    ],
                            ],
                    ],
            ]
    ];

The search results that come back are simply elasticsearch response elements serialized into an array. You can see an example of a response in the official elasticsearch documentation.

Algolia

You can just pass a string to search the index:

SearchIndex::getResults('look for this');

To perform more advanced queries an array may be passed. Read the official documentation to learn what's possible.

All other operations

For all other operations you can get the underlying client:

SearchIndex::getClient(); // will return the Elasticsearch or Algolia client.

Query helpers

If you're using Algolia you can use a SearchQuery-object to perform searches.

use Spatie\SearchIndex\Query\Algolia\SearchIndex();

$searchQuery = new SearchQuery();
$searchQuery->searchFor('my query')
            ->withFacet('facetName', 'facetValue');

//a searchQuery object may be passed to the getResults-function directly.
SearchIndex::getResults($searchQuery);

Tests

This package comes with a set of unit tests. Every time the package gets updated Travis CI will automatically run them.

You can also run them manually. You'll have first run composer install --dev to install phpspec. After that's out of the way you can run the tests with vendor/bin/phpspec run.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

About Spatie

Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Comments
  • Update README to support Elasticsearch 6

    Update README to support Elasticsearch 6

    Elasticsearch 6, the latest ES version, requires some things to be done different. Our package still works with this version, but the README is outdated and should address some things better.

    opened by brendt 3
  • Model is not recognized as Searchable object

    Model is not recognized as Searchable object

    I followed the instructions closely and encountered a problem by the time I reach the part where I get to use to upsertToIndex().

    I'm using Laravel 5.1 for this example. I have the Searchable interface saved at app\Spatie\SearchIndex\Searchable.php. My Model is as follows:

    <?php
    
    namespace App;
    
    use App\Spatie\SearchIndex\Searchable;
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model implements Searchable
    {
        public $fillable = ['title', 'content', 'tags'];
    
        /**
         * Returns an array with properties which must be indexed
         *
         * @return array
         */
        public function getSearchableBody()
        {
            $searchableProperties = [
                'title' => $this->title,
                'content' => $this->content
            ];
    
            return $searchableProperties;
        }
    
        /**
         * Return the type of the searchable subject
         *
         * @return string
         */
        public function getSearchableType()
        {
            return 'post';
        }
    
        /**
         * Return the id of the searchable subject
         *
         * @return string
         */
        public function getSearchableId()
        {
            return $this->id;
        }
    }
    

    My Controller as follows:

    class Posts extends Controller
    {
        public function index()
        {
            $post = Post::first();
    
            \SearchIndex::upsertToIndex($post);
        }
    }
    

    I'm getting the error:

    Argument 1 passed to Spatie\SearchIndex\SearchIndexHandlers\Elasticsearch::upsertToIndex() must be an instance of Spatie\SearchIndex\Searchable, instance of App\Post given, called in /home/vagrant/Code/laravel51/bootstrap/cache/compiled.php on line 5964 and defined
    

    I'm pretty sure I've implemented the interface properly, as removing any of these methods will throw an error reminding to implement the interface properly. The only difference from your README is that the example code uses "Eloquent" instead of "Model".

    opened by foxlance 3
  • Re-indexing an entire Model

    Re-indexing an entire Model

    Hi! TIA for a great package, looking forward to using it.

    I didn't see any documentation around reindexing an entire model. I recently added the package, but I now want to get my entire model into the index.

    Any suggestions how to do that?

    opened by dingman 2
  • [proposal] Add indexExists Method to Elasticsearch

    [proposal] Add indexExists Method to Elasticsearch

    Could we add a private indexExists() method inside the ElasticSearch - handler and adjust clearIndex() like this:

    public function clearIndex($indexName = null)
    {
        $indexName = $this->resolveIndexName($indexName);
    
        if (! $this-indexExists($indexName)) {
            return;
        }
    
        $this->elasticsearch->indices()->delete(['index' => $indexName]);
     }
    

    Cause the underlying ElasticSearch Client just throws an exception if there is no index to clear.

    Another possible implementation would be to allow setting an ignore parameter and pass this one along with the index into the delete request.

    What do you think?

    opened by Naoray 2
  • SearchIndex::clearIndex() Not Working with Elasticsearch 1.4

    SearchIndex::clearIndex() Not Working with Elasticsearch 1.4

    I have created a Elasticsearch 1.4 inside my homestead php 7 box. This was done from the Forge Recipe. I have successfully added to the index via the SearchIndex::upsertToIndex($model); method. But when I run the following command below its throwing 404 errors when it shouldn't be because I can hit them at localhost:9200/{indexName} without any issues.

    <?php
    
    namespace App\Console\Commands;
    
    use App\Models\Site;
    use Elasticsearch\Common\Exceptions\Missing404Exception;
    use Illuminate\Console\Command;
    use Illuminate\Support\Facades\Config;
    use Spatie\SearchIndex\SearchIndexFacade as SearchIndex;
    
    class ClearSearchIndex extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'app:search:clear';
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'Clear search index.';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Execute the console command.
         *
         * @return mixed
         */
        public function handle()
        {
            $index = Config::get('searchindex.elasticsearch.defaultIndexName');
            $sites = Site::all('full_domain');
    
            try {
                SearchIndex::clearIndex();
                $this->info("Cleared search index for: {$index}");
            } catch (Missing404Exception $e) {
                $this->comment("Index: {$index} not found.");
            }
    
            foreach($sites as $site) {
                Config::set('searchindex.elasticsearch.defaultIndexName', $site->full_domain);
                try {
                    SearchIndex::clearIndex();
                    $this->info("Cleared search index for: {$site->full_domain}");
                } catch (Missing404Exception $e) {
                    $this->comment("Index: {$site->full_domain} not found.");
                }
            }
        }
    }
    

    Was wondering if this is an issue on my end, or something that is an issue with the library. This is the following output that I get from doing the CLI command: https://www.dropbox.com/s/0t9bur06cl5dxt2/Screenshot%202016-03-31%2015.19.09.png?dl=0

    opened by iolson 2
  • Paginate

    Paginate

    Hi. Nice and easy to use implementation of elasticsearch. How can you implement pagination on the results consistent with laravel ? Do you need to do that in laravel?

    opened by Korogba 2
  • Add optional index name to use when performing Elasticsearch operations

    Add optional index name to use when performing Elasticsearch operations

    In the newest Elastic versions, multiple types per index aren't allowed anymore: https://www.elastic.co/blog/index-type-parent-child-join-now-future-in-elasticsearch

    This PR adds optional indexName arguments to make it easier to work with multiple indices.

    opened by brendt 1
  • Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase

    Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase

    I use the PHPUnit\Framework\TestCase notation instead of PHPUnit_Framework_TestCase while extending our TestCases. This will help us migrate to PHPUnit 6, that no longer support snake case class names.

    Just needed to bump PHPUnit version to 4.8.36, to keep compatibility.

    I didn't update to PHPUnit 5 'cause this package still supports PHP 5.5.

    opened by carusogabriel 1
  • Laravel 5.2 - Class searchIndex does not exist

    Laravel 5.2 - Class searchIndex does not exist

    Hi, I have a L5.2 application and all seems to be correctly configured.

    When I try to SearchIndex::upsertToIndex($createdModel);

    With the following use specified

    use Spatie\SearchIndex\SearchIndexFacade as SearchIndex;

    I get the error: Class searchIndex does not exist

    Any suggestions of obvious things I may have missed?

    opened by apstyx 1
  • Specify index in given query/upsert

    Specify index in given query/upsert

    Currently it is possible to set the default index to use (either for Algolia or ES) in the searchindex config. I noticed this block:

    /*
     * This index will be used whenever you don't explicitly
     * set one yourself.
     */
    'defaultIndexName' => 'main',
    

    There is nothing in the docs explaining how to "explicitly set one yourself" aside from in the config. Is this possible? E.g. \SearchIndex::upsertToIndex($product, 'products');. Could one update the config value at runtime? although I suppose the SearchIndex class in instantiated when the app is booted so will ignore any subsequent config value change.

    It would be nice to be able to specify which index to upsert/query to/from. Or would one normally have all records in the same index and filter out the ones not relevant? E.g. products/posts. Ideally this would be driver agnostic (e.g. work the same way for ES and Algolia).

    opened by harrygr 1
  • Support for ElasticSearch 2.0

    Support for ElasticSearch 2.0

    Presently, searchindex does not support the ElasticSearch 2.0 library for PHP. Is there a plan to add support for 2.0 while maintaining backwards compatibility with the 1.0 branch, perhaps via a separate branch in the searchindex project?

    opened by publiux 1
Releases(3.5.0)
Owner
Spatie
Webdesign agency based in Antwerp, Belgium
Spatie
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
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
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 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
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 driver for Laravel Scout

Elasticsearch driver for Laravel Scout. Contents Compatibility Installation Configuration Basic Usage Advanced Search Migrations Pitfalls Compatibilit

Ivan Babenko 197 Dec 19, 2022
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
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
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
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
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
Sphinx Search library provides SphinxQL indexing and searching features

Sphinx Search Sphinx Search library provides SphinxQL indexing and searching features. Introduction Installation Configuration (simple) Usage Search I

Ripa Club 62 Mar 14, 2022
Unmaintained: Laravel Searchy makes user driven searching easy with fuzzy search, basic string matching and more to come!

!! UNMAINTAINED !! This package is no longer maintained Please see Issue #117 Here are some links to alternatives that you may be able to use (I do no

Tom Lingham 533 Nov 25, 2022
Easily add weighted searches through model attributes and relationships

Laravel Searchable ?? Easily add weighted searches through model attributes and relationships. This package currently supports MySQL and PostgreSQL. I

H-FARM 93 Nov 1, 2022
symfony solarium integration and solr management

solarium-bundle symfony bundle for solarium integration and solr management. current state of this bundle for now this bundle is me messing about with

null 2 Jan 11, 2022
Fulltext indexing and searching for Laravel

Laravel fulltext index and search This package creates a MySQL fulltext index for models and enables you to search through those. Install Install with

SWIS 171 Jan 4, 2023