4

In search bar when i am searching a product using sku (MY-PRODUCT-101),

It displays all the product whose sku is having prefix (MY-PRODUCT-XXX) ,

But i only want it to fetch whose sku is (MY-PRODUCT-101).

1

Just create Plugin the customize and change the match strategie Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match and use around Plugin Function technique :

<?php
namespace Ibnab\OneSku\Plugin;
use Magento\Framework\DB\Helper\Mysql\Fulltext;
use Magento\Framework\DB\Select;
use Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface;
use Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface;
use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder;
use Magento\Framework\Search\Request\Query\BoolExpression;
use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext as FulltextResource;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection as AttributeCollection;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\ResourceConnection;
use Ibnab\OneSku\Helper\Data as OneSkuData;
class Match extends \Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match {
    const SPECIAL_CHARACTERS = '-+~/\\<>\'":*$#@()!,.?`=%&^';
    const MINIMAL_CHARACTER_LENGTH = 3;
    /**
     * @var string[]
     */
    private $replaceSymbols = [];
    /**
     * @var ResolverInterface
     */
    private $resolver;
    /**
     * @var Fulltext
     */
    private $fulltextHelper;
    /**
     * @var string
     */
    private $fulltextSearchMode;
    /**
     * @var PreprocessorInterface[]
     * @since 100.1.0
     */
    protected $preprocessors;
    /**
     * @var AttributeCollection
     */
    private $attributeCollection;
    /**
     * @var FulltextResource
     */
    private $fulltextResource;
    private $storeManager;
    private $_resource;</p>

<p>    /**
     * @var \Ibnab\PaymentFee\Helper\Data
     */
    protected $dataHelper;    
    /**
     * @param ResolverInterface $resolver
     * @param Fulltext $fulltextHelper
     * @param string $fulltextSearchMode
     * @param PreprocessorInterface[] $preprocessors
     */
    public function __construct(
    OneSkuData $dataHelper,AttributeCollection $attributeCollection, FulltextResource $fulltextResource, StoreManagerInterface $storeManage, ResourceConnection $resource, ResolverInterface $resolver, Fulltext $fulltextHelper, $fulltextSearchMode = Fulltext::FULLTEXT_MODE_BOOLEAN, array $preprocessors = []
    ) {        
        $this->resolver = $resolver;
        $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1);
        $this->fulltextHelper = $fulltextHelper;
        $this->fulltextSearchMode = $fulltextSearchMode;
        $this->preprocessors = $preprocessors;
        $this->attributeCollection = $attributeCollection;
        $this->fulltextResource = $fulltextResource;
        $this->storeManager = $storeManage;
        $this->_resource = $resource;
        $this->dataHelper = $dataHelper;
        parent::__construct($resolver,$fulltextHelper, $fulltextSearchMode, $preprocessors);
    }
    public function aroundBuild($matcher, $build, $scoreBuilder, $select, $query, $conditionType
    ) {
        /** @var $query \Magento\Framework\Search\Request\Query\Match */
        $resultSku = 0;
        $queryValue = $this->prepareQuery($query->getValue(), $conditionType);
        $fieldList = [];
        foreach ($query->getMatches() as $match) {
            $fieldList[] = $match['field'];
        }
        $resolvedFieldList = $this->resolver->resolve($fieldList);
        $fieldIds = [];
        $columns = [];
        foreach ($resolvedFieldList as $field) {
            if ($field->getType() === FieldInterface::TYPE_FULLTEXT && $field->getAttributeId()) {
                $fieldIds[] = $field->getAttributeId();
            }
            $column = $field->getColumn();
            $columns[$column] = $column;
        }
        if ($this->dataHelper->allowExtension()) {
        $attribute = $this->attributeCollection->getItemByColumnValue('attribute_code', 'sku');
        $attributeId = $attribute ? $attribute->getId() : 0;
        if ($attributeId != 0) {
            $connection = $this->_resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
            $mainFullTextScope = $this->fulltextResource->getMainTable() . "_scope" . $this->storeManager->getStore()->getId();
            $tblFullTextScope = $connection->getTableName($mainFullTextScope);
            $resultSku = $connection->fetchOne('SELECT count(entity_id) FROM `' . $tblFullTextScope . '` WHERE attribute_id=' . $attributeId . ' And data_index=\'' . $query->getValue() . '\'');
        }
        }
        if ($resultSku == 1) {
            $matchQuery = 'data_index=\'' . $query->getValue() . '\'';
        }else{
            $matchQuery = $this->fulltextHelper->getMatchQuery(
                    $columns, $queryValue, $this->fulltextSearchMode
            );     
        }
            $matchQuery = $this->fulltextHelper->getMatchQuery(
                    $columns, $queryValue, $this->fulltextSearchMode
            ); 
        $scoreBuilder->addCondition($matchQuery, true);
        if ($fieldIds) {
            $matchQuery = sprintf('(%s AND search_index.attribute_id IN (%s))', $matchQuery, implode(',', $fieldIds));
        }
        $select->where($matchQuery);
        return $select;
    }
}

in this class we have added some line to test of sku with some reference is exist by example in table catalogsearch_fulltext_scope1 (related to store id 1)

$attribute = $this->attributeCollection->getItemByColumnValue('attribute_code', 'sku');
$attributeId = $attribute ? $attribute->getId() : 0;
if ($attributeId != 0) {
    $connection = $this->_resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
    $mainFullTextScope = $this->fulltextResource->getMainTable() . "_scope" . $this->storeManager->getStore()->getId();
    $tblFullTextScope = $connection->getTableName($mainFullTextScope);
    $resultSku = $connection->fetchOne('SELECT count(entity_id) FROM `' . $tblFullTextScope . '` WHERE attribute_id=' . $attributeId . ' And data_index=\'' . $query->getValue() . '\'');
}

if yes we change the clause where to be strict equal without Boolean match or like .

if ($resultSku == 1) {
    $matchQuery = 'data_index=\'' . $query->getValue() . '\'';
}else{
    $matchQuery = $this->fulltextHelper->getMatchQuery(
            $columns, $queryValue, $this->fulltextSearchMode
    );     
}

You can visit the Full Course and download Free Extension for this task

0

Magento 1 has feature to set which kind of search you want.

but in Magento 2 that feature removed so you need to customize that magento-search module

for more detail check this which describe in detail as how all search type works : Search type details

  • Hello, Ronak, I have gone through this path but there is no option to change type of search. – Askit Raina Nov 4 '16 at 5:48
  • Sorry I had put Magento 1 path by mistake. – Ronak Chauhan Nov 4 '16 at 6:30
  • Magento 2 doesn't allow to select search type so you need to customize it. – Ronak Chauhan Nov 4 '16 at 6:31
  • Okay, Do uou have any idea in which file i have to do custom things? Can you please provide me the path of that particular file? – Askit Raina Nov 4 '16 at 6:39
0

The right way to introduce "exact" search is to extend existing query declared in magento2ce/app/code/Magento/CatalogSearch/etc/search_request.xml. Particullary quick_search_container request. You need to add "term" query which is equivalent of "term" elastic search query - https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html. You can find the examples of term request in the same file (advanced_search_container request).

The most reasonable place to extend is request->queries->query[quick_search_container]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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