ane. Overview

Elasticsearch is used every bit a search engine in Magento. Since Magento 2.four, Elasticsearch is a required component and installation of Magento without Elasticsearch is not possible.

To integrate Magento with Elasticsearch, the following steps are needed:

  • install proper version of Elasticsearch on the server
  • install proper version of PHP Elasticsearch library as a project dependency
  • specify the installed Elasticsearch version in Magento configuration ( Catalog > Itemize Search > Search Engine )

The version of Elasticsearch should be uniform with the Elasticsearch library and Magento. Magento has a split up module for each Elasticsearch version. Non every version is supported.

Past default, in that location is simply ane index in Elasticsearch for each Magento shop – search index for products. All existing query types use the same index. There are no indexes for other entities such as categories, customers or CMS pages.

Information technology is possible to create other indexes in Elasticsearch and new query types using these indexes, although it seems quite a large effort.

Magento ignores any indexes in Elasticsearch not defined in Magento, then it is possible to use the aforementioned case of Elasticsearch for other purposes.

Elasticsearch is used mainly in storefront. Regular search in admin panel does not use Elasticsearch.

two. Reindex

Data in Elasticsearch is always secondary data, synchronized with data in MySQL database. The procedure of synchronization is called reindex. Magento provides different ways of making reindex:

  1. Full reindex – which can be triggered manually by a programmer – in command line or in code
  2. Partial reindex – reindex of simply those products that actually inverse
    1. on save – reindex happens immediately when product is saved
    2. on schedule – saved product is but added to the queue of products waiting for reindex. A background procedure that runs every infinitesimal makes reindex of all products in queue asynchronously. This is a better option considering operation

The just Magento Indexer related to Elasticsearch is Catalog Search.

A production record in Elasticsearch looks like that:

          {    "store_id":"i",    "sku":"24-MB01",    "status":1,    "status_value":"Enabled",    "visibility":4,    "name":"joust duffle bag",    "url_key":"joust-duffle-purse",    "clarification":"The sporty Joust Duffle Purse tin't be beat out - non in the gym, not on the luggage carousel, not anywhere. Large enough to haul a basketball or soccer ball and some sneakers with plenty of room to spare, it'due south ideal for athletes with places to go. Dual acme handles. Adaptable shoulder strap. Full-length zipper. Fifty 29\" x West 13\" x H 11\".",    "category_ids":[       ii,       3,       4    ],    "position_category_2":"0",    "name_category_2":"Default Category",    "position_category_3":"0",    "name_category_3":"Gear",    "position_category_4":"0",    "name_category_4":"Bags",    "price_0_1":"34.000000",    "price_1_1":"34.000000",    "price_2_1":"34.000000",    "price_3_1":"34.000000" }                  

To index additional product information in Elasticsearch, the simplest solution is to create a product EAV attribute with proper parameters (e.g. Use due north Search = Yes, or Visible in Advanced Search = Yes).

It is also possible to create a simulated product attribute (static EAV attribute without actual column in database) and index an arbitrary value using a Magento plugin.

3. Search Asking

Requests to Elasticsearch are built based on configuration in search_request.xml files.

The files ascertain different query types. Past default, Magento uses the following query types:

  • quick_search_container – Quick Search (the regular search at the tiptop of the page)
  • advanced_search_container – Avant-garde Search
  • catalog_view_container – Category page with layered navigation
  • graphql_product_search_with_aggregation – used past GraphQL API
  • graphql_product_search – used by GraphQL API

In Magento Commerce B2B extension, at that place is i additional query type:

  • quick_order_suggestions_search_container used by Quick Order by SKU

Main search_request.xml file looks like that:

          <?xml version="1.0"?> <!-- /**  * Copyright © Magento, Inc. All rights reserved.  * Run into COPYING.txt for license details.  */ --> <requests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"           xsi:noNamespaceSchemaLocation="urn:magento:framework:Search/etc/search_request.xsd">     <asking query="quick_search_container" index="catalogsearch_fulltext">         <dimensions>             <dimension name="telescopic" value="default"/>         </dimensions>         <queries>             <query xsi:type="boolQuery" name="quick_search_container" boost="one">                 <queryReference clause="should" ref="search" />                 <queryReference clause="should" ref="partial_search" />                 <queryReference clause="must" ref="category"/>                 <queryReference clause="must" ref="price"/>                 <queryReference clause="must" ref="visibility"/>             </query>             <query xsi:type="matchQuery" value="$search_term$" name="search">                 <match field="*"/>             </query>             <query xsi:type="matchQuery" value="$search_term$" name="partial_search">                 <match field="*"/>                 <friction match field="name" matchCondition="match_phrase_prefix"/>                 <lucifer field="sku" matchCondition="match_phrase_prefix"/>             </query>             <query xsi:type="filteredQuery" proper noun="category">                 <filterReference clause="must" ref="category_filter"/>             </query>             <query xsi:blazon="filteredQuery" name="price">                 <filterReference clause="must" ref="price_filter"/>             </query>             <query xsi:type="filteredQuery" proper name="visibility">                 <filterReference clause="must" ref="visibility_filter"/>             </query>         </queries>         <filters>             <filter xsi:blazon="termFilter" proper name="category_filter" field="category_ids" value="$category_ids$"/>             <filter xsi:type="rangeFilter" name="price_filter" field="price" from="$price.from$" to="$price.to$"/>             <filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/>         </filters>         <aggregations>             <bucket proper noun="price_bucket" field="price" xsi:type="dynamicBucket" method="$price_dynamic_algorithm$">                 <metrics>                     <metric type="count"/>                 </metrics>             </saucepan>             <saucepan proper noun="category_bucket" field="category_ids" xsi:type="termBucket">                 <metrics>                     <metric type="count"/>                 </metrics>             </saucepan>         </aggregations>         <from>0</from>         <size>10000</size>     </request>     <request query="advanced_search_container" alphabetize="catalogsearch_fulltext">         <dimensions>             <dimension name="telescopic" value="default"/>         </dimensions>         <queries>             <query xsi:type="boolQuery" name="advanced_search_container" heave="1">                 <queryReference clause="should" ref="sku_query"/>                 <queryReference clause="should" ref="price_query"/>                 <queryReference clause="should" ref="category_query"/>                 <queryReference clause="must" ref="visibility_query"/>             </query>             <query name="sku_query" xsi:type="filteredQuery">                 <filterReference clause="must" ref="sku_query_filter"/>             </query>             <query name="price_query" xsi:blazon="filteredQuery">                 <filterReference clause="must" ref="price_query_filter"/>             </query>             <query proper noun="category_query" xsi:type="filteredQuery">                 <filterReference clause="must" ref="category_filter"/>             </query>             <query proper noun="visibility_query" xsi:type="filteredQuery">                 <filterReference clause="must" ref="visibility_filter"/>             </query>         </queries>         <filters>             <filter xsi:type="wildcardFilter" name="sku_query_filter" field="sku" value="$sku$"/>             <filter xsi:type="rangeFilter" proper name="price_query_filter" field="price" from="$price.from$" to="$price.to$"/>             <filter xsi:type="termFilter" name="category_filter" field="category_ids" value="$category_ids$"/>             <filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/>         </filters>         <from>0</from>         <size>10000</size>     </asking>     <asking query="catalog_view_container" index="catalogsearch_fulltext">         <dimensions>             <dimension name="scope" value="default"/>         </dimensions>         <queries>             <query xsi:type="boolQuery" proper name="catalog_view_container" boost="one">                 <queryReference clause="must" ref="category"/>                 <queryReference clause="must" ref="price"/>                 <queryReference clause="must" ref="visibility"/>             </query>             <query xsi:type="filteredQuery" proper name="category">                 <filterReference clause="must" ref="category_filter"/>             </query>             <query xsi:type="filteredQuery" proper noun="price">                 <filterReference clause="must" ref="price_filter"/>             </query>             <query xsi:type="filteredQuery" name="visibility">                 <filterReference clause="must" ref="visibility_filter"/>             </query>         </queries>         <filters>             <filter xsi:blazon="termFilter" proper name="category_filter" field="category_ids" value="$category_ids$"/>             <filter xsi:type="rangeFilter" proper noun="price_filter" field="price" from="$price.from$" to="$price.to$"/>             <filter xsi:type="termFilter" name="visibility_filter" field="visibility" value="$visibility$"/>         </filters>         <aggregations>             <bucket proper noun="price_bucket" field="price" xsi:blazon="dynamicBucket" method="$price_dynamic_algorithm$">                 <metrics>                     <metric blazon="count"/>                 </metrics>             </bucket>             <bucket proper noun="category_bucket" field="category_ids" xsi:type="termBucket">                 <metrics>                     <metric blazon="count"/>                 </metrics>             </bucket>         </aggregations>         <from>0</from>         <size>10000</size>     </request> </requests>                  

The xml mentions some product fields like visibility. Yet, since Magento allows creating custom product attributes, even in the admin panel, query generated by this xml is further modified to include all searchable product attributes.

This is washed past a plugin to xml reader:

          Magento\CatalogSearch\Model\Search\ReaderPlugin::afterRead() $result = array_merge_recursive(   $xmlData,   $this->requestGenerator->generate() );        

In RequestGenerator::generate(), Magento adds some dynamic changes to the search asking, including clauses related to product attributes. It is possible to add additional changes to the request using a similar mechanism.

This plugin is executed once and buried. To run across changes implemented in search_request.xml or added past plugins, it is necessary to make clean cache (and so this way, it is not possible to use dissimilar requests depending on customer, current date etc., although at that place may be other ways of implementing this).

Based on the xml and a listing of searchable attributes, Magento sends a request to Elasticsearch, which may await every bit follows:

          {    "from":0,    "size":12,    "query":{       "bool":{          "must":[             {                "terms":{                   "visibility":[                      "three",                      "4"                   ],                   "boost":1.0                }             }          ],          "should":[             {                "match":{                   "_search":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":truthful,                      "lenient":fake,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "name":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":fifty,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":6.0                   }                }             },             {                "match":{                   "sku":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "heave":7.0                   }                }             },             {                "lucifer":{                   "description":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":fifty,                      "fuzzy_transpositions":true,                      "lenient":imitation,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":2.0                   }                }             },             {                "match":{                   "short_description":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "friction match":{                   "manufacturer_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":truthful,                      "lenient":faux,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "status_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":simulated,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":ii.0                   }                }             },             {                "match":{                   "url_key":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "tax_class_id_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":fifty,                      "fuzzy_transpositions":truthful,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "heave":2.0                   }                }             },             {                "match":{                   "_search":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":l,                      "fuzzy_transpositions":true,                      "lenient":faux,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":2.0                   }                }             },             {                "match_phrase_prefix":{                   "proper noun":{                      "query":"my_search_term",                      "slop":0,                      "max_expansions":l,                      "boost":2.0                   }                }             },             {                "match_phrase_prefix":{                   "sku":{                      "query":"my_search_term",                      "slop":0,                      "max_expansions":50,                      "heave":2.0                   }                }             }          ],          "adjust_pure_negative":true,          "minimum_should_match":"1",          "boost":1.0       }    },    "stored_fields":[       "_id",       "_score"    ],    "sort":[       {          "_score":{             "order":"desc"          }       }    ],    "track_total_hits":2147483647,    "aggregations":{       "price_bucket":{          "extended_stats":{             "field":"price_0_1",             "sigma":two.0          }       },       "category_bucket":{          "terms":{             "field":"category_ids",             "size":500,             "min_doc_count":ane,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "social club":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       }    } }                  

The format of search_request.xml allows the use of the post-obit Elasticsearch queries:

  • boolQuery
  • matchQuery
  • filteredQuery

The number of search results is configured in search_request.xml, e.one thousand. <size>10</size>. Default: 10 000. 10 000 is likewise a default limit in Elasticsearch (index.max_result_window). If it is necessary to return more than ten 000 results, changes in lawmaking and Elasticsearch configuration may exist needed.

4. Category view page

Viewing the category folio is basically a kind of search and the logic is very similar to the logic of quick search.

The basic mechanism is equally follows:

  • Magento makes a request to Elasticsearch to find matching product ids
  • Based on the results from Elasticsearch, Magento loads the products from standard MySQL database (and may apply additional filters at this point)
  • Data from MySQL is displayed on the frontend.

Additionally, Magento uses Elasticsearch to get information nigh the number of matching products adjacent to each selection in layered navigation.

Case: customer enters category page Bags and selects some filters in layered navigation, e.g. Toll $xl.00-49.99

Category and filters are added to request url, e.g. http://mystore.pl/gear/bags.html?toll=twoscore-l

Magento parses the url parameters and makes request to Elasticsearch to go 2 pieces of information:

  • items – ids of products matching the new filters (but ids, no data)
  • aggregations – number of matching products for each option of each filter in layered navigation (after applying all new filters)

The asking may look like that:

          {    "from":0,    "size":12,    "query":{       "bool":{          "must":[             {                "term":{                   "category_ids":{                      "value":"4",                      "boost":1.0                   }                }             },             {                "range":{                   "price_0_1":{                      "from":"40",                      "to":"49.999",                      "include_lower":truthful,                      "include_upper":true,                      "boost":ane.0                   }                }             },             {                "terms":{                   "visibility":[                      "2",                      "4"                   ],                   "boost":1.0                }             }          ],          "adjust_pure_negative":true,          "heave":1.0       }    },    "stored_fields":[       "_id",       "_score"    ],    "sort":[       {          "position_category_4":{             "gild":"asc"          }       }    ],    "track_total_hits":2147483647,    "aggregations":{       "price_bucket":{          "extended_stats":{             "field":"price_0_1",             "sigma":2.0          }       },       "category_bucket":{          "terms":{             "field":"category_ids",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "society":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "manufacturer_bucket":{          "terms":{             "field":"manufacturer",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "color_bucket":{          "terms":{             "field":"color",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":faux,             "guild":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "activity_bucket":{          "terms":{             "field":"action",             "size":500,             "min_doc_count":i,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "style_bags_bucket":{          "terms":{             "field":"style_bags",             "size":500,             "min_doc_count":ane,             "shard_min_doc_count":0,             "show_term_doc_count_error":fake,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "material_bucket":{          "terms":{             "field":"cloth",             "size":500,             "min_doc_count":one,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "strap_bags_bucket":{          "terms":{             "field":"strap_bags",             "size":500,             "min_doc_count":ane,             "shard_min_doc_count":0,             "show_term_doc_count_error":imitation,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "features_bags_bucket":{          "terms":{             "field":"features_bags",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "gender_bucket":{          "terms":{             "field":"gender",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "category_gear_bucket":{          "terms":{             "field":"category_gear",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "size_bucket":{          "terms":{             "field":"size",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "club":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "eco_collection_bucket":{          "terms":{             "field":"eco_collection",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "performance_fabric_bucket":{          "terms":{             "field":"performance_fabric",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "gild":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "erin_recommends_bucket":{          "terms":{             "field":"erin_recommends",             "size":500,             "min_doc_count":i,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "guild":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "new_bucket":{          "terms":{             "field":"new",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "sale_bucket":{          "terms":{             "field":"sale",             "size":500,             "min_doc_count":ane,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "club":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "format_bucket":{          "terms":{             "field":"format",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "purpose_bucket":{          "terms":{             "field":"purpose",             "size":500,             "min_doc_count":ane,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "style_bottom_bucket":{          "terms":{             "field":"style_bottom",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":simulated,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "style_general_bucket":{          "terms":{             "field":"style_general",             "size":500,             "min_doc_count":i,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "sleeve_bucket":{          "terms":{             "field":"sleeve",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "guild":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "collar_bucket":{          "terms":{             "field":"collar",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "club":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "pattern_bucket":{          "terms":{             "field":"design",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":imitation,             "club":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       },       "climate_bucket":{          "terms":{             "field":"climate",             "size":500,             "min_doc_count":i,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       }    } }                  

Later receiving a list of products from Elasticsearch, Magento fetches the products from MySQL database. The SQL includes filter by ids from Elasticsearch + some additional filters. It may await like that:

          SELECT `east`.*,         `price_index`.`price`,         `price_index`.`tax_class_id`,         `price_index`.`final_price`,         IF(price_index.tier_price IS Non Nothing, Least(price_index.min_price,                                                price_index.tier_price),         price_index.min_price)                   Equally `minimal_price`,         `price_index`.`min_price`,         `price_index`.`max_price`,         `price_index`.`tier_price`,         Ifnull(review_summary.reviews_count, 0)  AS `reviews_count`,         Ifnull(review_summary.rating_summary, 0) As `rating_summary`,         `stock_status_index`.`stock_status`      AS `is_salable`  FROM   `catalog_product_entity` AS `e`         INNER Bring together `catalog_product_index_price` Every bit `price_index`                 ON price_index.entity_id = due east.entity_id                    AND price_index.customer_group_id = 0                    AND price_index.website_id = '1'         LEFT Bring together `review_entity_summary` AS `review_summary`                ON e.entity_id = review_summary.entity_pk_value                   AND review_summary.store_id = 1                   AND review_summary.entity_type = (SELECT                       `review_entity`.`entity_id`                                                     FROM   `review_entity`                                                     WHERE  ( entity_code =                                                              'product' ))         INNER Bring together `cataloginventory_stock_status` Every bit `stock_status_index`                 ON due east.entity_id = stock_status_index.product_id  WHERE  ( ( stock_status_index.stock_status = one )           AND ( due east.entity_id IN ( 4, v, 13, 14 ) ) )         AND ( e.created_in <= 1 )         AND ( e.updated_in > 1 )  ORDER  BY Field(e.entity_id, iv, five, 13, 14);                  

In this SQL, the post-obit part is based on the results from Elasticsearch:

          eastward.entity_id IN ( 4, 5, thirteen, 14 ).        

This is really filter by category and cost.

The logic of filtering based on choices in layered navigation is applied to Elasticsearch request only. The logic of filtering based on visibility (production visibility, category permissions etc.) is applied twice: showtime as part of Elasticsearch request, then again as role of the SQL. Therefore, information technology might happen that production that should be visible is non visible due to invalid data in Elasticsearch, merely it should not happen that product that should be invisible is visible due to invalid data in Elasticsearch.

Custom lawmaking that applies additional visibility filters should too apply the filters twice. If the filter is applied to MySQL only, it is possible that the displayed number of products found will be higher than the actual number of products on the page.

After loading products, Magento builds the view of layered navigation. Each filter is a select with options. For each option, Magento presents the number of matching products. This number comes from Elasticsearch (aggregations).

In previous versions of Magento, there was a choice to use MySQL instead of Elasticsearch for fulltext search. At that time, MySQL EAV indexer was used to support layered navigation. According to Magento documentation, if the merchant uses Elasticsearch for fulltext search and at that place is no custom extension depending on EAV indexer, EAV indexer is non needed and can be disabled in the configuration: Stores > Settings > Configuration > Itemize > Catalog > Catalog Search > Enable EAV Indexer.

Layered navigation can be hidden by a change in the layout XML file. Notwithstanding, the underlying logic of layered navigation cannot exist disabled without considerable attempt.

Product attributes are bachelor in layered navigation based on their parameters

  • Use in Layered Navigation (code "is_filterable") – layered navigation on the category page
  • Employ in Search Results Layered Navigation (code "is_filterable_in_search") – layered navigation on search results page

Merely some information types and input types can be used in layered navigation. E.thou. text attributes cannot be used in layered navigation.

If there is some mismatch between Elasticsearch and MySQL, the mutual indicators are:

  • products that should be visible are not visible on a list, but can be accessed straight using product page url
  • the count of products displayed in some place of the page does not friction match the actual number of products visible

Category page is cached by full folio cache, and so the search actually takes place only one time, the beginning time any client enters the page. Subsequent customers from the same group receive page from cache, so no asking to Elasticsearch or MySQL is made. Flushing full page cache is necessary to refresh search results.

Each category has a parameter "Is Ballast": Aye or No.

If there is a category structure like that:

Juices

  Orange juices

If Juices has the parameter "Is Anchor" = Yeah, Juices will also prove Orange Juices. If Juices has the parameter "Is Ballast" = No, Juices will only display products directly assigned to category Juices.

v. Quick Search

The basic mechanism is as follows:

  • Magento makes a request to Elasticsearch to find matching production ids
  • Based on the results from Elasticsearch, Magento loads the products from standard MySQL database (and may apply boosted filters at this bespeak)
  • Data from MySQL is displayed on the frontend.

Information kept in Elasticsearch is never really displayed on the frontend. It is simply used for searching, merely once the production is institute, it is loaded from the MySQL database and all data comes from MySQL.

Case: if product name is Cat in MySQL and Canis familiaris in Elasticsearch:

  • When you lot type "True cat", y'all become 0 results
  • When you type "Dog", you tin can see a production named "Cat" in the results

If production is not indexed in Elasticsearch, information technology cannot be institute.

Attributes used for search include some basic attributes + EAV attributes with proper backdrop, eastward.g. Use in Search – Yes

Asking to Elasticsearch may look like that:

          {    "from":0,    "size":12,    "query":{       "bool":{          "must":[             {                "terms":{                   "visibility":[                      "3",                      "4"                   ],                   "heave":ane.0                }             }          ],          "should":[             {                "friction match":{                   "_search":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":fake,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":ii.0                   }                }             },             {                "match":{                   "proper noun":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":truthful,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":half-dozen.0                   }                }             },             {                "lucifer":{                   "sku":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":l,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":vii.0                   }                }             },             {                "match":{                   "description":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":faux,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "short_description":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":truthful,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "heave":2.0                   }                }             },             {                "lucifer":{                   "manufacturer_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":fifty,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "status_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":simulated,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "heave":2.0                   }                }             },             {                "match":{                   "url_key":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "match":{                   "tax_class_id_value":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":imitation,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":truthful,                      "boost":2.0                   }                }             },             {                "friction match":{                   "_search":{                      "query":"my_search_term",                      "operator":"OR",                      "prefix_length":0,                      "max_expansions":50,                      "fuzzy_transpositions":true,                      "lenient":false,                      "zero_terms_query":"NONE",                      "auto_generate_synonyms_phrase_query":true,                      "boost":2.0                   }                }             },             {                "match_phrase_prefix":{                   "name":{                      "query":"my_search_term",                      "slop":0,                      "max_expansions":fifty,                      "boost":two.0                   }                }             },             {                "match_phrase_prefix":{                   "sku":{                      "query":"my_search_term",                      "slop":0,                      "max_expansions":l,                      "boost":2.0                   }                }             }          ],          "adjust_pure_negative":true,          "minimum_should_match":"i",          "heave":1.0       }    },    "stored_fields":[       "_id",       "_score"    ],    "sort":[       {          "_score":{             "gild":"desc"          }       }    ],    "track_total_hits":2147483647,    "aggregations":{       "price_bucket":{          "extended_stats":{             "field":"price_0_1",             "sigma":ii.0          }       },       "category_bucket":{          "terms":{             "field":"category_ids",             "size":500,             "min_doc_count":1,             "shard_min_doc_count":0,             "show_term_doc_count_error":false,             "order":[                {                   "_count":"desc"                },                {                   "_key":"asc"                }             ]          }       }    } }                  

By default, Magento uses OR condition, so if you type "sku1 sku2", y'all may find two products. If you type "orange juice", you may find orange t-shirt and raspberry juice.

A search request sent to Elasticsearch includes many clauses, e.g. the name should be "Cat", the description should be "Cat", a curt description should exist "Cat". Information technology is enough for one clause to be true to detect a  production. This depends on Elasticsearch parameter  minimum_should_match, which has a value of 1 difficult-coded in Magento.

If y'all make a typo in a search term, Magento does not show the product in search results, but there may be a search suggestion ("Did you mean …?") with a given production. If y'all blazon just the middle part of a discussion – the aforementioned effect as for typos. Search suggestions are a separate feature of Magento and they are provided past a divide asking to Elasticsearch.

In Magento Commerce, there is a configuration for which customer groups tin apply search bar (Category Permissions > Disallow Itemize Search Past).

The search results page has layered navigation that allows to further filter the results. There is a split list of attributes that can be used in layered navigation in the category page vs. search result folio.

6. Advanced Search

Advanced search is like to quick search, merely the client can configure search details.

Attributes are displayed in advanced search form based on parameter: Visible in Avant-garde Search.

7. GraphQL

GraphQL is ane of Magento APIs. It allows external systems to fetch data from Magento. GraphQL allows to get a listing of products. In that location is an endpoint that allows to go a list of products based on fulltext search, which uses pretty much the same logic as search on storefront.

eight. Search suggestions

Search Suggestions is an additional feature of Magento Commerce, information technology displays a block "Did you mean?" on the search results page.

Suggestions are loaded from Elasticsearch past a dissever query that may look as follows:

          {    "suggest":{       "text":"my_search_term",       "phrase_style_general_value":{          "phrase":{             "analyzer":"standard",             "field":"style_general_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"style_general_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_style_bags_value":{          "phrase":{             "analyzer":"standard",             "field":"style_bags_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":ane.0,             "separator":" ",             "max_errors":one.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"style_bags_value",                   "min_word_length":three,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_strap_bags_value":{          "phrase":{             "analyzer":"standard",             "field":"strap_bags_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"strap_bags_value",                   "min_word_length":3,                   "min_doc_freq":one.0                }             ]          }       },       "phrase_eco_collection_value":{          "phrase":{             "analyzer":"standard",             "field":"eco_collection_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"eco_collection_value",                   "min_word_length":iii,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_color_value":{          "phrase":{             "analyzer":"standard",             "field":"color_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"color_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_features_bags_value":{          "phrase":{             "analyzer":"standard",             "field":"features_bags_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"features_bags_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_allow_open_amount_value":{          "phrase":{             "analyzer":"standard",             "field":"allow_open_amount_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":i.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"allow_open_amount_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_country_of_manufacture_value":{          "phrase":{             "analyzer":"standard",             "field":"country_of_manufacture_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"country_of_manufacture_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_manufacturer_value":{          "phrase":{             "analyzer":"standard",             "field":"manufacturer_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":one.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"manufacturer_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_format_value":{          "phrase":{             "analyzer":"standard",             "field":"format_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"format_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_giftcard_type_value":{          "phrase":{             "analyzer":"standard",             "field":"giftcard_type_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":ten,             "direct_generator":[                {                   "field":"giftcard_type_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_climate_value":{          "phrase":{             "analyzer":"standard",             "field":"climate_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"climate_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_collar_value":{          "phrase":{             "analyzer":"standard",             "field":"collar_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"collar_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_description":{          "phrase":{             "analyzer":"standard",             "field":"description",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"description",                   "min_word_length":three,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_sale_value":{          "phrase":{             "analyzer":"standard",             "field":"sale_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"sale_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_price_view_value":{          "phrase":{             "analyzer":"standard",             "field":"price_view_value",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":x,             "direct_generator":[                {                   "field":"price_view_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_custom_layout_update_file_value":{          "phrase":{             "analyzer":"standard",             "field":"custom_layout_update_file_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":x,             "direct_generator":[                {                   "field":"custom_layout_update_file_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_is_returnable_value":{          "phrase":{             "analyzer":"standard",             "field":"is_returnable_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":i.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"is_returnable_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_page_layout_value":{          "phrase":{             "analyzer":"standard",             "field":"page_layout_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"page_layout_value",                   "min_word_length":3,                   "min_doc_freq":one.0                }             ]          }       },       "phrase_gift_wrapping_available_value":{          "phrase":{             "analyzer":"standard",             "field":"gift_wrapping_available_value",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"gift_wrapping_available_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_shipment_type_value":{          "phrase":{             "analyzer":"standard",             "field":"shipment_type_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":i.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"shipment_type_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_msrp_display_actual_price_type_value":{          "phrase":{             "analyzer":"standard",             "field":"msrp_display_actual_price_type_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":ane.0,             "separator":" ",             "max_errors":one.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"msrp_display_actual_price_type_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_purpose_value":{          "phrase":{             "analyzer":"standard",             "field":"purpose_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":ane.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"purpose_value",                   "min_word_length":iii,                   "min_doc_freq":one.0                }             ]          }       },       "phrase_size_value":{          "phrase":{             "analyzer":"standard",             "field":"size_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"size_value",                   "min_word_length":3,                   "min_doc_freq":one.0                }             ]          }       },       "phrase_status_value":{          "phrase":{             "analyzer":"standard",             "field":"status_value",             "size":ii,             "real_word_error_likelihood":0.95,             "conviction":one.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"status_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_custom_design_value":{          "phrase":{             "analyzer":"standard",             "field":"custom_design_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"custom_design_value",                   "min_word_length":3,                   "min_doc_freq":one.0                }             ]          }       },       "phrase_options_container_value":{          "phrase":{             "analyzer":"standard",             "field":"options_container_value",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"options_container_value",                   "min_word_length":3,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_style_bottom_value":{          "phrase":{             "analyzer":"standard",             "field":"style_bottom_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":i.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"style_bottom_value",                   "min_word_length":iii,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_tax_class_id_value":{          "phrase":{             "analyzer":"standard",             "field":"tax_class_id_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":one.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"tax_class_id_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_short_description":{          "phrase":{             "analyzer":"standard",             "field":"short_description",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":one.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"short_description",                   "min_word_length":iii,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_activity_value":{          "phrase":{             "analyzer":"standard",             "field":"activity_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"activity_value",                   "min_word_length":3,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_custom_layout_value":{          "phrase":{             "analyzer":"standard",             "field":"custom_layout_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"custom_layout_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_quantity_and_stock_status_value":{          "phrase":{             "analyzer":"standard",             "field":"quantity_and_stock_status_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":ane.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"quantity_and_stock_status_value",                   "min_word_length":iii,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_name":{          "phrase":{             "analyzer":"standard",             "field":"name",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":i.0,             "force_unigrams":true,             "token_limit":ten,             "direct_generator":[                {                   "field":"name",                   "min_word_length":iii,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_category_gear_value":{          "phrase":{             "analyzer":"standard",             "field":"category_gear_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":i.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"category_gear_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_gender_value":{          "phrase":{             "analyzer":"standard",             "field":"gender_value",             "size":ii,             "real_word_error_likelihood":0.95,             "conviction":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"gender_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_sleeve_value":{          "phrase":{             "analyzer":"standard",             "field":"sleeve_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":ane.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"sleeve_value",                   "min_word_length":three,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_performance_fabric_value":{          "phrase":{             "analyzer":"standard",             "field":"performance_fabric_value",             "size":2,             "real_word_error_likelihood":0.95,             "conviction":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"performance_fabric_value",                   "min_word_length":iii,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_material_value":{          "phrase":{             "analyzer":"standard",             "field":"material_value",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":x,             "direct_generator":[                {                   "field":"material_value",                   "min_word_length":iii,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_pattern_value":{          "phrase":{             "analyzer":"standard",             "field":"pattern_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"pattern_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_erin_recommends_value":{          "phrase":{             "analyzer":"standard",             "field":"erin_recommends_value",             "size":two,             "real_word_error_likelihood":0.95,             "conviction":1.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"erin_recommends_value",                   "min_word_length":three,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_url_key":{          "phrase":{             "analyzer":"standard",             "field":"url_key",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":10,             "direct_generator":[                {                   "field":"url_key",                   "min_word_length":iii,                   "min_doc_freq":ane.0                }             ]          }       },       "phrase_visibility_value":{          "phrase":{             "analyzer":"standard",             "field":"visibility_value",             "size":two,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":truthful,             "token_limit":ten,             "direct_generator":[                {                   "field":"visibility_value",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_sku":{          "phrase":{             "analyzer":"standard",             "field":"sku",             "size":ii,             "real_word_error_likelihood":0.95,             "confidence":one.0,             "separator":" ",             "max_errors":i.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"sku",                   "min_word_length":3,                   "min_doc_freq":i.0                }             ]          }       },       "phrase_gift_message_available_value":{          "phrase":{             "analyzer":"standard",             "field":"gift_message_available_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":1.0,             "separator":" ",             "max_errors":ane.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"gift_message_available_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       },       "phrase_new_value":{          "phrase":{             "analyzer":"standard",             "field":"new_value",             "size":2,             "real_word_error_likelihood":0.95,             "confidence":i.0,             "separator":" ",             "max_errors":1.0,             "force_unigrams":true,             "token_limit":10,             "direct_generator":[                {                   "field":"new_value",                   "min_word_length":3,                   "min_doc_freq":1.0                }             ]          }       }    } }                  

At that place is a hardcoded limit of max_errors = one, then the feature will not provide relevant results when client makes more than one typo.

Elasticsearch returns a list of suggestions with a score for each attribute separately (sku, name, description, …).

Suggestions are displayed fifty-fifty if there are right results.

9. Additional search features

It is possible to meet popular search terms in admin console: Marketing > SEO & Search > Search Terms

This characteristic uses MySQL database only.

It is likewise possible to define a redirect for a search term, e.g. when a client types "Juices", he/she may exist redirected to the category page of Juices (or whatever other page). However, at that place needs to exist an exact match. This feature does not use Elasticsearch.

It is also possible to specify synonyms for search:

At that place is a feature of Search Recommendations ("Related search terms"), which is similar but different from search suggestions.

ten. Vue Storefront

Vue Storefront is a frontend PWA application which can exist continued to Magento. Vue Storefront uses Elasticsearch every bit NoSQL database. Entities from Magento are indexed in Elasticsearch, so that Vue Storefront can access them directly without requests to Magento.

Indexing of data from Magento is done by custom application mage2vuestorefront (https://github.com/vuestorefront/mage2vuestorefront) written in Javascript that fetches information from Magento using Magento Rest API. It supports many entities such every bit categories, product reviews, CMS pages.

Elasticsearch has a lot of strengths and is the most powerful search engine, bachelor for free. It analyzes a high book of data in almost real-time, providing users with needed results immediately. It provides a lot of features that are worth to be discovered and applied to your eCommerce shop.
If you need any assist with your store and would similar to discuss how Elasticsearch tin can be used in your business, contact us and we will be pleased to assist yous.