> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lunarphp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Extending Search

## Overview

Good search is the backbone of any storefront so Lunar aims to make this as extensible as possible so you can index what
you need for your front-end, without compromising on what we require our side in the hub.

There are three things to consider when you want to extend the search:

* Searchable fields
* Sortable fields
* Filterable fields

## Default index values

Eloquent models which use the `Lunar\Base\Traits\Searchable` trait will use an indexer class to tell Scout how each it
should be indexed, if an indexer isn't mapped in the config the default `EloquentIndexer` (provided by Lunar) will be
used.

This class will map a basic set of fields to the search index:

* The ID of the model
* Any `searchable` attributes.

Some models require a bit more information to be indexed, such as SKU's, prices etc. For these scenarios, dedicated
indexers have been created and are mapped in the config already.

#### `Lunar\Search\ProductIndexer`

Fields which are indexed:

* The ID of the model
* Any `searchable` attributes.
* The product `status`
* The product `product_type`
* The `brand` (if applicable)
* The ProductVariant `skus` related to the product.
* The `created_at` timestamp

## Mapping custom indexers

All indexers are mapped in `config/search.php` under `indexers`, if a model isn't mapped here then it will
simply use the default `ELoquentIndexer`. To change how each model is indexed, simply map it like so:

```php theme={null}
return [
    // ...
    'indexers' => [
        Lunar\Models\Product::class => App\Search\CustomProductIndexer::class,
    ],
],
```

## Creating a custom indexer

To create your own indexer, simply create a custom class like so:

```php theme={null}
<?php

namespace App\Search;

use Lunar\Search\ScoutIndexer;

class CustomProductIndexer extends ScoutIndexer
{
    // Scout method to return the index name.
    public function searchableAs(Model $model): string
    {
        return 'custom_index_name';
    }
    
    // Scout method to return whether the model should be searchable.
    public function shouldBeSearchable(Model $model): bool
    {
        return true;
    }
    
    // Scout method to allow you to tap into eager loading.
    public function makeAllSearchableUsing(Builder $query): Builder
    {
        return $query->with([
            'thumbnail',
            'variants',
            'productType',
            'brand',
        ]);
    }
    
    // Scout method to get the ID used for indexing
    public function getScoutKey(Model $model): mixed
    {
        return $model->getKey();
    }
    
    // Scout method to get the column used for the ID.
    public function getScoutKeyName(Model $model): mixed
    {
        return $model->getKeyName();
    }
    
    // Simple array of any sortable fields.
    public function getSortableFields(): array 
    {
        return [
            'created_at',
            'updated_at',
        ];
    }
    
    // Simple array of any filterable fields.
    public function getFilterableFields(): array 
    {
        return [
            '__soft_deleted',
        ];
    }
    
    // Return an array representing what should be sent to the search service i.e. Algolia
    public function toSearchableArray(Model $model, string $engine): array
    {
        return array_merge([], $this->mapSearchableAttributes($model));
    }
}
```

The `EloquentIndexer` class implements the `Lunar\Search\Interfaces\ModelIndexerInterface` so if your class doesn't
extend the Eloquent one, you must implement this interface.

There are some methods which are available just on the `EloquentIndexer` but not defined on the interface are:

#### mapSearchableAttributes

```php theme={null}
mapSearchableAttributes(Model $model): array
```

This method will take all `searchable` attributes for the model attribute type and map them into the index,
this means when you add searchable attributes in the hub they will automatically be added to the index.
