studioespresso / craft-scout

Craft Scout provides a simple solution for adding full-text search to your entries. Scout will automatically keep your search indexes in sync with your entries.
MIT License
81 stars 54 forks source link

Incorrect indexing of disabled commerce products under some circumstances #330

Open mike-moreau opened 2 months ago

mike-moreau commented 2 months ago

I am importing a list of products from a json feed into Craft Commerce as Products. Some Products are created as enabled and some created as disabled.

In the Control Panel, I have verified that the value for enabled is coming in as expected.

Scout begins indexing only the enabled products correctly. But after the 20th product in the json feed, all subsequent products are indexed whether their status is enabled or disabled.

I have confirmed by passing "enabled" and "status" attributes into the Algolia index that the products are indeed disabled when they were indexed.

To resolve this temporarily I am including this code at the top of my transformer function.

public static function transform(Entry|Product|Asset $element)
    {
        if (!$element->enabled) {
            return [];
// ...

However, it feels like there is a bug here, and I'd like to understand the underlying issue rather than leave a check in the transformer.

Here is some debugging info. I'd be glad to provide more if it's helpful.

This is a multisite install with separate indexes for English and Spanish products.

The Scout config criteria looks like this:

return [
    'sync' => App::env('ALGOLIA_ENABLED'),
    'batch_size' => 1,
    'indexRelations' => false,
    'indices' => [
        ScoutIndex::create('en_products')
            ->elementType(Product::class)
            ->transformer([ScoutTransformer::class, 'transform'])
            ->criteria(fn(ProductQuery $query) => $query->site('en'))
            ->splitElementsOn(PRODUCTS_SPLIT_ELEMENTS_ON)
            ->indexSettings(
                IndexSettings::create()
                    ->ranking(PRODUCTS_RANKING_ORDER)
                    ->customRanking(PRODUCTS_CUSTOM_RANKING)
                    ->distinct(true)
                    ->attributeForDistinct('distinctID')
                    ->attributesForFaceting(PRODUCTS_ATTRIBUTES_FOR_FACETING)
                    ->searchableAttributes(PRODUCTS_SEARCHABLE_ATTRIBUTES)
                    ->indexLanguages(['en'])
                    ->queryLanguages(['en'])
            ),
//...

In my import Queue job, I call saveElement on the Product and then afterward on the default variant.

// ....
        if (!Craft::$app->elements->saveElement($product, true, true, true, true)) {
            if ($product->hasErrors()) {
                Craft::error('Errors: ' . print_r($product->getErrors(), true), __METHOD__);
            }

            throw new Exception('Could not save product "' . $product->title . '". Please check the log folder for errors.');
        }

        $variant = $product->defaultVariant;
        if (!$variant) {
            throw new Exception("No default variant found for '{$product->title}'");
        }

        $variant->title = $this->cleanTitle($this->part['PartName']);
        $variant->sku = $newSku;
        $variant->price = $newPrice;
        $variant->hasUnlimitedStock = false;
        $variant->stock = $newStock;
        $variant->length = $newLength;
        $variant->width = $newWidth;
        $variant->height = $newHeight;
        $variant->weight = $newWeight;

        if (!Craft::$app->elements->saveElement($variant, true, true, true)) {
            if ($variant->hasErrors()) {
                Craft::error('Errors: ' . print_r($product->getErrors(), true), __METHOD__);
            }

            throw new Exception("Could not save the default variant of '{$product->title}'");
        }
// end of import queue job for product

Do you have any insight as to why some disabled products skip being indexed while later disabled products get indexed? Thanks for reading this through!