> ## 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

Search indexing can be extended to customize searchable, sortable, and filterable fields.

## Overview

Good search is the backbone of any storefront, so Lunar aims to make this as extensible as possible. Custom fields can be indexed for the storefront without compromising what Lunar requires for the admin panel.

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 model
should be indexed. If an indexer isn't mapped in the config, the default `ScoutIndexer` (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/lunar/search.php` under `indexers`. If a model isn't mapped here, the default
`ScoutIndexer` is used. To change how each model is indexed, 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 Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
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 e.g. Algolia
    public function toSearchableArray(Model $model): array
    {
        return array_merge([], $this->mapSearchableAttributes($model));
    }
}
```

The `ScoutIndexer` class implements the `Lunar\Search\Interfaces\ScoutIndexerInterface` interface. If a custom indexer
does not extend `ScoutIndexer`, it must implement this interface directly.

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

#### 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.
