Precise search by super attributes

Edit on GitHub

Task to achieve

Imagine a shop selling a laptop (abstract product) with 16/32Gb RAM and i5/i7 CPU options. One day there are only two models in stock: 16Gb + i5 and 32Gb + i7.

Selecting in the search RAM: 16Gb + CPU: i7 shows you this abstract product in the catalog/search, while none of it’s concretes match the requirements.

It’s expected, that only products with at least one concrete matching selected super-attribute values must be shown. In the previously mentioned example, the search result must be empty.

Possible solutions

The following solutions require Product Page Search 3.0.0 or newer.

Solution 1. Concrete products index as a support call

The solution consists of several steps: the idea, implementation plan, and possible downsides of the solution.

Idea

Search is done in two steps:

  1. In the product concrete index, search is performed by super attributes and matching product abstract IDs are displayed.
  2. Those from the main index for product abstracts are retrieved.

Implementation

  1. Extend ProductConcretePageSearchTransfer with new field attributes, where desired attributes would be stored as an array of string values:
<property name="attributes" type="string[]" singular="attribute"/>
  1. Implement Data expander with the interface \Spryker\Zed\ProductPageSearchExtension\Dependency\Plugin\ProductConcretePageDataExpanderPluginInterface in order to fill into ProductConcretePageSearchTransfer super attributes from the concrete.
  2. Add this plugin in ProductPageSearchDependencyProvider into plugins list getProductConcretePageDataExpanderPlugins.
  3. Implement the query expander ConcreteProductSearchQueryExpanderPlugin implementing interface QueryExpanderPluginInterface. You have to add this plugin before FacetQueryExpanderPlugin in CatalogDependencyProvider into list createCatalogSearchQueryExpanderPlugins.

This plugin does the following:

  • Filters out from the request values for super attributes and doesn’t include those in the query.
  • Makes a sub-search request like CatalogClient::searchProductConcretesByFullText, but searches by facets of super attributes from the request.
  • Adds into query list of unique abstract product IDs.

An example implementation looks as follows:

some code here
  1. Extend FacetQueryExpanderPlugin, which doesn’t take into account facets used in the plugin ConcreteProductSearchQueryExpanderPlugin.

An example implementation looks as follows:

some code here

Make sure to use updated plugin in CatalogDependencyProvider.

Downsides

As you see from the implementation, the results of the last query abstract products index cannot be actually paginated. You can’t deal with smooth pagination since it’s unknown how many concrete products to skip or query to get the next page with abstract products.

Solution 2: Concrete products index is used as a main search index

The solution consists of several steps: the idea, implementation plan, and possible downsides of the solution.

Idea

The search request is made on the concrete product index, which is extended with attributes, to allow filter by those, and with abstract product data to fulfill required abstract product information for catalog display.

Implementation plan

  1. Update product concrete data loader.
  2. Update ProductConcretePageSearchPublisher to load into ProductConcreteTransfers more data, needed to populate abstract product data.
  3. Update ProductConcreteSearchDataMapper to use productAbstractMapExpanderPlugins.
  4. Update the query plugin used to point to concrete index, using ProductConcreteCatalogSearchQueryPlugin in CatalogDependencyProvider::createCatalogSearchQueryPlugin.

Downsides

You get duplicate abstract products in the search results, accompanied by a single concrete product.

Consider merging duplicated abstract products, if you don’t want duplicates on the page.