Shopware 6: How to index

Today I learned how the indexer worked. I knew already, that while indexing in the backend you can decide which indexer not to run.

Screenshot of the shopware backend of the cache and indexing section. The indexer drowndown is shown completely. In the dropdown one can read 'Skip indexers and/or updaters'

But what I didn’t know, it is the same on the CLI with dal:refresh:index.

If you look into the cli command help we can check the options:

19:18:15 ~/var/www/current $ bin/console dal:refresh:index --help
Description:
Refreshes the index for a given entity

Usage:
dal:refresh:index [options]

Options:
--use-queue Ignore cache and force generation
--skip=SKIP Comma separated list of indexSo er names to be skipped
--only=ONLY Comma separated list of indexer names to be generated
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
-e, --env=ENV The Environment name. [default: "prod"]
--no-debug Switch off debug mode.
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

We are interested in --only and --skip. What I wanted to do:

bin/console dal:refresh:index --only=product.search-keyword

I got the name of the indexer from the administration.

But nothing happend, so I dug into the code.

// \Shopware\Core\Framework\DataAbstractionLayer\Command\RefreshIndexCommand::execute
protected function execute(InputInterface $input, OutputInterface $output): int
{
    $this->io = new ShopwareStyle($input, $output);

    $skip = \is_string($input->getOption('skip')) ? explode(',', (string) $input->getOption('skip')) : [];
    $only = \is_string($input->getOption('only')) ? explode(',', (string) $input->getOption('only')) : [];

    $this->registry->index($input->getOption('use-queue'), $skip, $only);

    $skipEntities = array_map(fn ($indexer) => str_replace('.indexer', '', (string) $indexer), $skip);

    $onlyEntities = array_map(fn ($indexer) => str_replace('.indexer', '', (string) $indexer), $only);

    $event = new RefreshIndexEvent(!$input->getOption('use-queue'), $skipEntities, $onlyEntities);
    $this->eventDispatcher->dispatch($event);

    return self::SUCCESS;
}

In the command implementation except that the indexer needs to be seperated by comma. For me, this was know, but hopefully you read the help text carefully.

So let’s look into the index method:

\Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexerRegistry::index
public function index(bool $useQueue, array $skip = [], array $only = []): void
{
    foreach ($this->indexer as $indexer) {
        if (\in_array($indexer->getName(), $skip, true)) {
            continue;
        }

        if (\count($only) > 0 && !\in_array($indexer->getName(), $only, true)) {
            continue;
        }

        $offset = null;

        $this->dispatcher->dispatch(new ProgressStartedEvent($indexer->getName(), $indexer->getTotal()));

        while ($message = $indexer->iterate($offset)) {
            $message->setIndexer($indexer->getName());
            $message->addSkip(...$skip);

            $this->sendOrHandle($message, $useQueue);

            $offset = $message->getOffset();

            try {
                $count = \is_array($message->getData()) ? \count($message->getData()) : 1;
                $this->dispatcher->dispatch(new ProgressAdvancedEvent($count));
            } catch (\Exception) {
            }
        }

        $this->dispatcher->dispatch(new ProgressFinishedEvent($indexer->getName()));
    }
}

And this is interesting and is as on the administration. We can filter with only and skip by indexer – unfortunately product.search-keyword is not an indexer in this sense. But a process? updater? Whatever we want to call it, we can only skip any but not limit it to one of the processes.

TL;DR – if you only want to reindex the search keywords, your cli command must look like this:

19:27:38 ~/var/www/current $  bin/console dal:refresh:index --use-queue --only=product.indexer --skip=product.inheritance,product.stock,product.variant-listing,product.child-count,product.many-to-many-id-field,product.category-denormalizer,product.cheapest-price,product.rating-averaget,product.stream,product.seo-url

We run only the product.indexer and skip everything which is not the product.search-keyword.

One thought on “Shopware 6: How to index

Leave a Reply

Discover more from Winkelwagen

Subscribe now to keep reading and get access to the full archive.

Continue reading