Fix: Correcting shape of indexed products

This commit is contained in:
2026-08-27 11:32:20 +03:00
parent e95ea4a43c
commit e4342da44a
3 changed files with 23 additions and 19 deletions
+14 -10
View File
@@ -16,7 +16,7 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
* Extends Lunar's own indexer so Modules\Core\Product\Services\ProductService can
* serve both listing/filtering AND single-product lookups from Meilisearch alone —
* one data source, no separate database read path for a product detail page. Adds:
* - collections (ids, filterable) and collection_names (display)
* - collections: [{id, name}, ...] — filterable via `collections.id`
* - slugs (every locale's Url::slug for the product, filterable) — lets
* ProductService::getBySlug() resolve a product from the index directly, with
* no database read at all
@@ -24,9 +24,9 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
* - variants: sku, stock, purchasable, option values, prices, media
* - the full media gallery (not just the single thumbnail Lunar's base indexer sends)
* - tags
* - reviews: public-safe fields only (see mapReview() — reviewer_email is deliberately
* excluded, it's PII with no storefront use), including staff replies, plus an
* average rating
* - reviews: {items: [...], count, average_rating} — items are public-safe fields
* only (see mapReview() — reviewer_email is deliberately excluded, it's PII with
* no storefront use), including staff replies
* - channel_ids (filterable) — Lunar's base indexer only indexes "status" as
* filterable, not channel assignment, so search results can't otherwise be
* scoped to products actually assigned+enabled on the current sales channel
@@ -49,7 +49,7 @@ class ProductIndexer extends BaseProductIndexer
...parent::getFilterableFields(),
'id',
'brand',
'collections',
'collections.id',
'price',
'slugs',
'channel_ids',
@@ -85,16 +85,20 @@ class ProductIndexer extends BaseProductIndexer
$currency = Currency::getDefault();
$reviews = ProductReview::where('product_id', $model->id)->with('media')->get();
$data['collections'] = $model->collections->pluck('id')->map(fn ($id) => (string) $id)->all();
$data['collection_names'] = $model->collections->map(fn ($collection) => $collection->translateAttribute('name'))->all();
$data['collections'] = $model->collections->map(fn ($collection) => [
'id' => $collection->id,
'name' => $collection->translateAttribute('name'),
])->all();
$data['slugs'] = $model->urls->pluck('slug')->unique()->values()->all();
$data['tags'] = $model->tags->pluck('value')->all();
$data['media'] = $model->media->map(fn (Media $media) => $this->mapMedia($media))->all();
$data['variants'] = $model->variants->map(fn (ProductVariant $variant) => $this->mapVariant($variant, $currency))->all();
$data['price'] = $this->cheapestPrice($model, $currency);
$data['reviews'] = $reviews->map(fn (ProductReview $review) => $this->mapReview($review))->all();
$data['review_count'] = $reviews->count();
$data['average_rating'] = $reviews->isEmpty() ? null : round($reviews->avg('rating'), 1);
$data['reviews'] = [
'items' => $reviews->map(fn (ProductReview $review) => $this->mapReview($review))->all(),
'count' => $reviews->count(),
'average_rating' => $reviews->isEmpty() ? null : round($reviews->avg('rating'), 1),
];
$data['channel_ids'] = $model->channels()
->wherePivot('enabled', true)
->pluck('lunar_channels.id')
+1 -1
View File
@@ -157,7 +157,7 @@ class ProductService
}
$clauses = Collection::make([
$filters->collectionId !== null ? "collections = \"{$filters->collectionId}\"" : null,
$filters->collectionId !== null ? "collections.id = \"{$filters->collectionId}\"" : null,
$filters->brand !== null ? 'brand = "'.addcslashes($filters->brand, '"\\').'"' : null,
$filters->minPrice !== null ? "price >= {$filters->minPrice}" : null,
$filters->maxPrice !== null ? "price <= {$filters->maxPrice}" : null,