Skip to main content
Lunar provides search indexing and querying through Laravel Scout with support for multiple search engines.

Overview

Search in Lunar is built on Laravel Scout, providing a flexible, driver-based search system. Scout’s database driver offers basic search out of the box, while more powerful engines like Meilisearch and Typesense can be swapped in for advanced features such as faceted filtering and relevance tuning. All search configuration lives in config/lunar/search.php. This file controls which models are indexed, which search engine each model uses, and which indexer class prepares the data for each model.
For building storefront search with faceted filtering, sorting, and structured results, see the Storefront Search add-on. It provides a Search facade with a consistent API across all search engines.

Configuration

Soft Deletes

By default, Scout sets the soft_delete option to false. This must be set to true in config/scout.php, otherwise soft-deleted models will appear in search results.
// config/scout.php
'soft_delete' => true,

Searchable Models

The models array in config/lunar/search.php defines which models are indexed. Lunar registers the following models by default:
'models' => [
    // These models are required by the system, do not change them.
    Lunar\Models\Brand::class,
    Lunar\Models\Collection::class,
    Lunar\Models\Customer::class,
    Lunar\Models\Order::class,
    Lunar\Models\Product::class,
    Lunar\Models\ProductOption::class,

    // Below you can add your own models for indexing...
    // App\Models\Example::class,
],
To add custom models to the search index, append them to this array. Custom models must use the Lunar\Base\Traits\Searchable trait.

Engine Mapping

By default, Scout uses the driver defined by the SCOUT_DRIVER environment variable for all models. This means if SCOUT_DRIVER is set to meilisearch, every searchable model gets indexed via Meilisearch. This may not always be desirable. For example, indexing orders in a paid service like Algolia alongside products would unnecessarily increase record counts and cost. Lunar allows specifying a different driver per model using the engine_map configuration:
'engine_map' => [
    Lunar\Models\Product::class => 'typesense',
    Lunar\Models\Order::class => 'meilisearch',
    Lunar\Models\Collection::class => 'meilisearch',
],
Any model not listed in the engine_map falls back to the default Scout driver.

Searchable Trait

All searchable Lunar models use the Lunar\Base\Traits\Searchable trait. This trait extends Scout’s Searchable trait and delegates key behavior to an indexer class:
  • searchableAs() — returns the index name
  • toSearchableArray() — returns the data to index
  • shouldBeSearchable() — determines whether the model should be indexed
  • searchableUsing() — returns the engine based on the engine_map configuration
  • getFilterableAttributes() — returns filterable fields for the engine
  • getSortableAttributes() — returns sortable fields for the engine
The trait resolves the appropriate indexer from the indexers config, falling back to the base Lunar\Search\ScoutIndexer if no specific indexer is mapped.

Indexers

Each searchable model is paired with an indexer class that controls what data is sent to the search engine. The indexers config maps models to their indexer:
'indexers' => [
    Lunar\Models\Brand::class => Lunar\Search\BrandIndexer::class,
    Lunar\Models\Collection::class => Lunar\Search\CollectionIndexer::class,
    Lunar\Models\Customer::class => Lunar\Search\CustomerIndexer::class,
    Lunar\Models\Order::class => Lunar\Search\OrderIndexer::class,
    Lunar\Models\Product::class => Lunar\Search\ProductIndexer::class,
    Lunar\Models\ProductOption::class => Lunar\Search\ProductOptionIndexer::class,
],

Default Indexer

The base Lunar\Search\ScoutIndexer class indexes:
  • The model’s id
  • Any attributes marked as searchable
It also handles TranslatedText attribute fields, creating locale-suffixed entries (e.g., name_en, name_fr) in the index.

Product Indexer

The Lunar\Search\ProductIndexer indexes the following fields:
FieldSource
idProduct ID
statusProduct status
product_typeProduct type name
brandBrand name (if present)
created_atUnix timestamp
thumbnailThumbnail URL (small variant)
skusArray of variant SKUs
Attribute handlesValues from searchable attributes
Sortable fields: created_at, updated_at, skus, status Filterable fields: __soft_deleted, skus, status

Order Indexer

The Lunar\Search\OrderIndexer indexes the following fields:
FieldSource
idOrder ID
channelChannel name
referenceOrder reference
customer_referenceCustomer reference
statusOrder status
placed_atPlacement timestamp
created_atUnix timestamp
sub_totalSub-total value
totalTotal value
currency_codeCurrency code
chargesTransaction references
linesProduct line descriptions and identifiers
{type}_first_name, {type}_last_name, etc.Address fields prefixed by type (shipping/billing)
tagsArray of tag values
Sortable fields: customer_id, user_id, channel_id, created_at, updated_at, total Filterable fields: customer_id, user_id, status, placed_at, channel_id, tags, __soft_deleted

Customer Indexer

The Lunar\Search\CustomerIndexer indexes the following fields:
FieldSource
idCustomer ID
nameFull name
company_nameCompany name
tax_identifierTax identifier
account_refAccount reference
created_atUnix timestamp
user_emailsArray of associated user emails
Meta fieldsAny meta key-value pairs
Attribute handlesValues from searchable attributes
Sortable fields: created_at, updated_at, name, company_name Filterable fields: __soft_deleted, name, company_name

Brand Indexer

The Lunar\Search\BrandIndexer indexes the following fields:
FieldSource
idBrand ID
nameBrand name
created_atUnix timestamp
Attribute handlesValues from searchable attributes
Sortable fields: created_at, updated_at, name Filterable fields: __soft_deleted, name

Collection Indexer

The Lunar\Search\CollectionIndexer indexes the following fields:
FieldSource
idCollection ID
created_atUnix timestamp
Attribute handlesValues from searchable attributes
Sortable fields: created_at, updated_at, name Filterable fields: __soft_deleted, name

ProductOption Indexer

The Lunar\Search\ProductOptionIndexer indexes the following fields:
FieldSource
idProductOption ID
name_{locale}Option name per locale
label_{locale}Option label per locale
option_{id}_{locale}Option value names per locale
Sortable fields: created_at, updated_at Filterable fields: __soft_deleted

Indexing Records

To import or refresh search indexes, use the lunar:search:index artisan command:
php artisan lunar:search:index
This imports all models listed in the models configuration.

Command Options

OptionDescription
modelsOne or more model class names to index (space-separated). Merged with config models by default.
--ignoreOnly index the models specified in the command, ignoring the config file.
--refreshDelete existing records from the index before reimporting.
--flushDelete records from the index without reimporting. Cannot be combined with --refresh.
# Refresh only the product index
php artisan lunar:search:index "Lunar\Models\Product" --refresh

# Flush the order index
php artisan lunar:search:index "Lunar\Models\Order" --flush

# Index only specific models, ignoring config
php artisan lunar:search:index "Lunar\Models\Product" "Lunar\Models\Brand" --ignore

Meilisearch Setup

When using Meilisearch, run the setup command to configure filterable and sortable attributes on Meilisearch indexes:
php artisan lunar:meilisearch:setup
This command reads the filterable and sortable fields from each model’s indexer and applies them to the corresponding Meilisearch index.

Storefront Search Add-on

For storefront search features such as faceted filtering, sorting, pagination, and structured response data, install the Storefront Search add-on:
composer require lunarphp/search
The add-on provides a Search facade with support for Meilisearch, Typesense, and database drivers, returning consistent SearchResults objects with hits, facets, and pagination. To customize what data is indexed for a model, create a custom indexer class. See the Extending Search guide for details on creating custom indexers, adding sortable and filterable fields, and mapping searchable attributes.