Overview
Every Lunar model that can be searched uses theLunar\Core\Models\Concerns\Searchable trait, which wraps Laravel Scout’s own Laravel\Scout\Searchable trait. Instead of implementing Scout’s methods directly on the model, the trait delegates them to an indexer class, resolved from config('lunar.search.indexers'). This keeps indexing logic out of the model and makes it swappable per model.
There are three things to consider when extending search:
- Which models are searchable
- What data is sent to the index (searchable, sortable, and filterable fields)
- Which search engine a model’s index lives on
Making a custom model searchable
Any Eloquent model, not just Lunar’s own models, can be added to the search index. Add theSearchable trait to the model:
config/lunar/search.php under models:
Only models listed in
models are picked up by the lunar:search:index artisan command. See the Search reference for indexing commands.Default indexing behavior
If a model isn’t mapped in theindexers config, Lunar\Core\Search\ScoutIndexer is used by default. Its toSearchableArray() indexes:
- The model’s
id - Any attributes marked
searchableon the model’s attribute data (viamapSearchableAttributes())
ScoutIndexer also exposes two protected helpers that a custom indexer can call when extending it:
searchable for the model’s attribute type into the index. This means attributes marked searchable in the admin panel are automatically added to the index without further code changes. TranslatedText attribute values are exploded into locale-suffixed keys (for example, name_en, name_fr).
name or description) into locale-suffixed index keys, the same way translatable attributes are handled. A plain, non-translatable string column is indexed under its bare field name.
Lunar’s own models are mapped to dedicated indexers that extend ScoutIndexer to add fields specific to that model. Lunar\Core\Search\ProductIndexer, for example, adds:
public_idandstatusproduct_type(the product type’s name) andbrand(the brand’s name, if set)created_atas a Unix timestamp- Translatable
name,description, andshort_descriptionfields, exploded per locale - Any searchable custom attributes
thumbnail(the small variant’s URL, if a thumbnail is set)skus, an array of the product’s variant SKUs
created_at, updated_at, skus, and status; its filterable fields are __soft_deleted, skus, and status.
Lunar ships similar dedicated indexers for BrandIndexer, CollectionIndexer, CustomerIndexer, OrderIndexer, and ProductOptionIndexer. See the Search reference for what each one indexes.
Mapping custom indexers
All indexers are mapped inconfig/lunar/search.php under indexers. To change how a model is indexed, map it to a custom class:
Creating a custom indexer
A custom indexer can extendLunar\Core\Search\ScoutIndexer to reuse its helpers, or implement Lunar\Core\Search\Interfaces\ScoutIndexerInterface directly if none of the default behavior is needed:
config/lunar/search.php:
Custom search engines
Mapping a model to a different engine
By default, Scout indexes every searchable model using the driver set by theSCOUT_DRIVER environment variable. To send a specific model’s index to a different engine, for example keeping high-volume order data off a paid service used for products, map it under engine_map in config/lunar/search.php:
engine_map falls back to the default Scout driver.
Registering a new engine
Adding an entirely new search engine (one that isn’t already a Scout driver) is not something Lunar reinvents: theSearchable trait resolves engines through Laravel Scout’s own Laravel\Scout\EngineManager, so a custom engine is registered the standard Scout way, using EngineManager::extend():
engine_map:
The storefront search package (namespace
Lunar\Search\...) is a separate package from the indexing pieces described on this page. It provides the storefront-facing query layer: faceted filtering, sorting, and instant search, built on top of the Scout search results that Lunar’s core indexers produce. Indexers control what gets indexed; Lunar\Search\... controls how the storefront queries it. See the Search reference for details.