6

I am using Magento 2 with elastic search enabled. I have a custom filtering of the product collection.

Now, when elastic search is enabled, custom filtering don't work however with MySQL search, it does work.

Any idea what's causing the issue or how elastic search is creating the product collection query?

3
  • have you already tried to launch a full reindex? Once you set ElasticSearch you need to generate all the documents reindexing the catalog. Apr 1, 2020 at 14:34
  • Did you ever figure this out? I am facing the same issue. Which version of magento are you on? Apr 24, 2020 at 20:27
  • Any solution for that? Jun 18, 2021 at 15:50

2 Answers 2

12

Just been through the same fun! Here is the solution for custom collections layered nav, specifically for Elastic Search;

Create a plugin based on your version;

Elastic Search 5 (built in)

<type name="Magento\Elasticsearch\Model\Client\Elasticsearch">
    <plugin name="pixie_customcollection_elastic_product_index" type="PixieMedia\CustomCollection\Model\Plugin\ElasticLayerPlugin" />
</type>

Elastic Search 6 (built in)

<type name="Magento\Elasticsearch6\Model\Client\Elasticsearch">
    <plugin name="pixie_customcollection_elastic_product_index" type="PixieMedia\CustomCollection\Model\Plugin\ElasticLayerPlugin" />
</type>

Amasty Elastic Search module (third party)

 <type name="Amasty\ElasticSearch\Model\Client\Elasticsearch">
    <plugin name="pixie_customcollection_elastic_product_index" type="PixieMedia\CustomCollection\Model\Plugin\ElasticLayerPlugin" />
</type>

Then the plugin itself - note the difference;

This version for built in ES 5 or 6;

namespace PixieMedia\CustomCollection\Model\Plugin;


class ElasticLayerPlugin
{


protected $cHelper;


public function __construct(
\PixieMedia\CustomCollection\Helper\Search $cHelper
) {
$this->cHelper = $cHelper;
}



public function beforeQuery($subject,$query) {


    // This is where to fetch the entity_id array to filter the Elastic collection with
    $filteredIds   = $this->cHelper->filterCollectionIds();

    if(!$filteredIds || count($filteredIds) < 1)  { 

        return [$query]; 
    }

    // Add the entity_id filter to the Elastic collection
    $query['body']['query']['bool']['filter'] = ['ids' => [ 'values' => $filteredIds]];


    return [$query];

}




}

This version for Amasty Elastic Search module;

namespace PixieMedia\CustomCollection\Model\Plugin;


class ElasticLayerPlugin
{


protected $cHelper;


public function __construct(
\PixieMedia\CustomCollection\Helper\Search $cHelper
) {
$this->cHelper = $cHelper;
}



public function beforeSearch($subject,$query) {


    // This is where to fetch the entity_id array to filter the Elastic collection with
    $filteredIds   = $this->cHelper->filterCollectionIds();

    if(!$filteredIds || count($filteredIds) < 1)  { 

        return [$query]; 
    }

    // Add the entity_id filter to the Elastic collection
    $query['body']['query']['bool']['filter'] = ['ids' => [ 'values' => $filteredIds]];


    return [$query];

}




}

Problem solved :)

11
  • Above provided solution working fine with native Elasticsearch 6, great thanks. Sep 22, 2020 at 10:29
  • Could you please share the helper? \PixieMedia\CustomCollection\Helper\Search Feb 13, 2021 at 16:21
  • @MagentoAaron You need to create a helper file inside create a function which have the product collection with same filters that you applied while overriding product collection for list page then from that helper function return array of product ids.
    – Yogita
    Jun 23, 2021 at 4:55
  • @pixiemedia Its working with Elasticsearch 7 too, thanks.
    – Yogita
    Jun 23, 2021 at 4:56
  • @pixiemedia Can you share the same for Mirasvit elastic search extension Sep 2, 2021 at 13:05
1
<?php

namespace PixieMedia\CustomCollection\Helper;

use \Magento\Framework\App\Helper\AbstractHelper;

class Search extends AbstractHelper
{
     public function __construct(
        \Magento\Framework\App\RequestInterface $request,
       \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollection
    )
    {
        $this->_request = $request;
        $this->productCollection = $productCollection;
    }


    public function filterCollectionIds()
    {
        $Filterids =[];
        $params = $this->_request->getParams();


        $collection = $this->productCollection->create();

        if (array_key_exists("is_product",$params)) {

             $collection->addAttributeToFilter(array(
                array('attribute' => 'type_id', 'eq' => 'simple'),
                array('attribute' => 'type_id', 'eq' => 'configurable'),
                array('attribute' => 'is_product', 'eq' => '1'),                
                
            ));
              } else if (array_key_exists("is_project",$params)) {


            $collection->addAttributeToFilter(array(                
                array('attribute' => 'type_id', 'eq' => 'grouped'), 
                array('attribute' => 'is_project', 'eq' => '1'),                
       
            ));

        }  
        

        foreach ($collection as $product) {
            $Filterids[] =$product->getEntityId();
        }

        return $Filterids;

    }
}
1
  • @pixiemedia, is it possible to pass sql query or collection instead of array in $query['body']['query']['bool']['filter'] Ex $query['body']['query']['bool']['filter'] = 'select id from products where product ....
    – S.P
    Jul 30, 2022 at 17:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.