Edit in GitHubLog an issue

Create a custom indexer

This topic discusses how to create a custom indexer. We've recently made a performance improvement that enables you to declare one or more shared indexers; if one of the shared indexes is already up-to-date, it doesn't need to be reindexed.

To implement your own indexer, add the following code in your module:

Custom indexer logic#

Your custom indexer class should implement \Magento\Framework\Indexer\ActionInterface, and the indexer should be able to perform three types of operations:

  • Row reindex: processing a single entry from a dictionary; responsibility of executeRow($id)
  • List reindex: processing a set of dictionary entries; responsibility of executeList($ids), where $ids is an array of entity IDs
  • Full reindex: processing all entities from a specific dictionary; responsibility of executeFull()

Indexer configuration#

Declare a new indexer process in the etc/indexer.xml file with the following attributes:

AttributeRequired?Description
idYesA unique indexer ID
classNoThe class that processes indexer methods (executeFull, executeList, executeRow)
primaryNoThe source provider
shared_indexNoUse this option to improve performance if your indexer is related to another indexer. In this example, if the Catalog Product Rule index needs to be reindexed, but other catalog product rule indexes are up-to-date, then only the Catalog Product Rule is reindexed.
view_idNoThe ID of the view element that is defined in the mview.xml configuration file.

For example,

Copied to your clipboard
1<?xml version="1.0"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd">
3 <indexer id="design_config_grid" view_id="design_config_dummy" class="Magento\Theme\Model\Indexer\Design\Config" primary="design_config">
4 ...
5 </indexer>
6</config>

An indexer process can also have the following optional parameters:

ParameterDescription
descriptionThe description of indexer to be displayed on the System > Tools > Index Management page.
fieldsetDescribes the fields, source, and data provider of the flat index table.
saveHandlerAn extension point. The class for processing (deleting, saving, updating) items when indexing.
structureThe class that processes (creates, removes) flat index tables.
titleThe title of indexer to be displayed on the System > Tools > Index Management page.

For example:

Copied to your clipboard
1<?xml version="1.0"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd">
3 <indexer ...>
4 <title translate="true">Design Config Grid</title>
5 <description translate="true">Rebuild design config grid index</description>
6
7 <fieldset name="design_config" source="Magento\Theme\Model\ResourceModel\Design\Config\Scope\Collection"
8 provider="Magento\Theme\Model\Indexer\Design\Config\FieldsProvider">
9 <field name="store_website_id" xsi:type="filterable" dataType="int"/>
10 <field name="store_group_id" xsi:type="filterable" dataType="int"/>
11 <field name="store_id" xsi:type="filterable" dataType="int"/>
12 </fieldset>
13 <saveHandler class="Magento\Framework\Indexer\SaveHandler\Grid"/>
14 <structure class="Magento\Framework\Indexer\GridStructure"/>
15 </indexer>
16</config>

All indexers related to a module should be declared in one file.

MView configuration#

Add the mview.xml configuration file in the etc module directory, where you declare the following:

  • indexer view ID
  • indexer class
  • the database tables the indexer tracks
  • what column data is sent to the indexer

Example

All Mview declarations related to a module should be declared in one file.

Example of a custom indexer implementation#

To push best-selling products to the top of a category listing, process statistics about sales to change the product position dynamically.

Assuming your module is named <VendorName>_Merchandizing, you must write the appropriate code in the indexer class Merchandizing/Model/Indexer/Popular.php

Copied to your clipboard
1<?php
2namespace <VendorName>\Merchandizing\Model\Indexer;
3
4class Popular implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
5{
6 /*
7 * Used by mview, allows process indexer in the "Update on schedule" mode
8 */
9 public function execute($ids){
10 //Used by mview, allows you to process multiple placed orders in the "Update on schedule" mode
11 }
12
13 /*
14 * Will take all of the data and reindex
15 * Will run when reindex via command line
16 */
17 public function executeFull(){
18 //Should take into account all placed orders in the system
19 }
20
21 /*
22 * Works with a set of entity changed (may be massaction)
23 */
24 public function executeList(array $ids){
25 //Works with a set of placed orders (mass actions and so on)
26 }
27
28 /*
29 * Works in runtime for a single entity using plugins
30 */
31 public function executeRow($id){
32 //Works in runtime for a single order using plugins
33 }
34}

Next, declare the indexer in Merchandizing/etc/indexer.xml:

Copied to your clipboard
1<?xml version="1.0"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd">
3 <indexer id="merchandizing_popular" view_id="merchandizing_popular_order" class="Vendor\Merchandizing\Model\Indexer\Popular">
4 <title translate="true">Popular Products</title>
5 <description translate="true">Sort products in a category by popularity</description>
6 </indexer>
7</config>

In this file, declare a new indexer process with the attribute:

  • id - To identify this indexer. Check status, mode or reindex this indexer by command line.
  • view_id - Id of view element which will be defined in the mview configuration file.
  • class - The name to the class which we process indexer method.

Finally, declare the indexer view (merchandizing_popular_order) that tracks sales (Merchandizing/etc/mview.xml):

Copied to your clipboard
1<?xml version="1.0" encoding="UTF-8"?>
2<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Mview/etc/mview.xsd">
3 <view id="merchandizing_popular_order" class="Vendor\Merchandizing\Model\Indexer\Popular" group="indexer">
4 <subscriptions>
5 <table name="sales_order" entity_column="entity_id" />
6 </subscriptions>
7 </view>
8</config>

These settings start <VendorName>\Merchandizing\Model\Indexer\Popular::execute method every time an order is changed.

After this, please refresh the cache and go to System > Tools > Index Management through the Admin to verify the custom indexer result.

Custom indexer modes

Now when an order is placed, the Popular Products indexer calculates the sorting order of the products by popularity and stores this data in the index table, so that it can be used in product displaying logic.

Use the following command to reindex the custom indexer:

Copied to your clipboard
bin/magento indexer:reindex merchandizing_popular

Use the following command to invalidate the custom indexer:

Copied to your clipboard
bin/magento indexer:reset merchandizing_popular
Was this helpful?
  • Privacy
  • Terms of Use
  • Do not sell my personal information
  • AdChoices
Copyright © 2022 Adobe. All rights reserved.