Overview
Search indexing in Lunar core is built on Laravel Scout. Scout’s database driver provides basic search with no extra services to run, while engines such as Meilisearch can be used instead for faster, more capable search. All search configuration lives inconfig/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.
Configuration
Publish the config file with:Soft Deletes
By default, Scout sets thesoft_delete option to false. Set this to true in config/scout.php so that soft-deleted models are excluded from search results.
Searchable Models
Themodels array in config/lunar/search.php defines which models are indexed. Lunar registers the following models by default:
Lunar\Core\Models\Concerns\Searchable trait.
Engine Mapping
By default, Scout uses the driver defined by theSCOUT_DRIVER environment variable for every model. This means that if SCOUT_DRIVER is set to meilisearch, every searchable model is indexed via Meilisearch.
This is not always desirable. For example, indexing orders in a paid service alongside products unnecessarily increases record counts and cost. The engine_map configuration key sets a different driver per model:
engine_map falls back to the default Scout driver.
The Searchable Trait
Every searchable Lunar model uses theLunar\Core\Models\Concerns\Searchable trait, which wraps Scout’s own Searchable trait and delegates behavior to a resolved indexer instance:
searchableAs()— returns the index nametoSearchableArray()— returns the data to indexshouldBeSearchable()— determines whether the model should be indexedsearchableUsing()— returns the engine, resolved from theengine_mapconfigurationgetFilterableAttributes()— returns filterable fields for the enginegetSortableAttributes()— returns sortable fields for the enginegetScoutKey()/getScoutKeyName()— the key and key name used to index the modelmakeAllSearchableUsing()— modifies the query used when bulk-importing the model
config('lunar.search.indexers'), falling back to the base Lunar\Core\Search\ScoutIndexer if the model has no dedicated entry.
Indexers
Each searchable model is paired with an indexer class implementingLunar\Core\Search\Interfaces\ScoutIndexerInterface, which controls what data is sent to the search engine and which of those fields are sortable or filterable. The indexers config maps models to their indexer:
Default Indexer
Lunar\Core\Search\ScoutIndexer is the base indexer, used for any model not listed in indexers. It indexes:
- The model’s
id - Any custom attributes marked as searchable, via
Lunar\Core\Facades\AttributeManifest::getSearchableAttributes()
Lunar\Core\FieldTypes\TranslatedText) are exploded into locale-suffixed keys (for example name_en, name_fr) rather than indexed as a single field.
Sortable fields: created_at, updated_at
Filterable fields: __soft_deleted
Product Indexer
Lunar\Core\Search\ProductIndexer indexes the following fields:
Sortable fields:
created_at, updated_at, skus, status
Filterable fields: __soft_deleted, skus, status
Order Indexer
Lunar\Core\Search\OrderIndexer indexes the following fields:
Sortable fields:
customer_id, user_id, channel_id, created_at, updated_at, closed_at, total
Filterable fields: customer_id, user_id, payment_status, fulfilment_status, closed, placed_at, channel_id, tags
The Table Rate Shipping add-on adds a
shipping_zone field to the order index when it is installed.Customer Indexer
Lunar\Core\Search\CustomerIndexer indexes the following fields:
Sortable fields:
created_at, updated_at, name, company_name
Filterable fields: __soft_deleted, name, company_name
Brand Indexer
Lunar\Core\Search\BrandIndexer indexes the following fields:
Sortable fields:
created_at, updated_at, name
Filterable fields: __soft_deleted, name
Collection Indexer
Lunar\Core\Search\CollectionIndexer indexes the same shape of data as the Brand indexer: id, public_id, created_at, the translatable name/description/short_description columns exploded per locale, and searchable custom attribute values.
Sortable fields: created_at, updated_at, name
Filterable fields: __soft_deleted, name
ProductOption Indexer
Lunar\Core\Search\ProductOptionIndexer indexes the following fields:
Sortable fields:
created_at, updated_at
Filterable fields: __soft_deleted
Custom Indexers
To customize what data is indexed for a model, implementLunar\Core\Search\Interfaces\ScoutIndexerInterface (or extend Lunar\Core\Search\ScoutIndexer) and map the model to it under the indexers key in config/lunar/search.php:
Indexing Records
To import or refresh search indexes, use thelunar:search:index Artisan command:
models configuration, using Scout’s scout:import and scout:flush commands under the hood.
Command Options
Meilisearch
Configuring Meilisearch as the Scout driver makes Lunar’s indexers write data suitable for facet and sort filtering, but Meilisearch also needs to know which fields on each index are filterable and sortable. The Meilisearch add-on provides alunar:meilisearch:setup command that reads each model’s getFilterableAttributes() and getSortableAttributes() (both defined by the indexer) and applies them to the corresponding Meilisearch index.