0

i am working on a module which will change the search criteria from OR to AND. This module will fetch exact product while search.

2 Answers 2

0

You have to extend below file in custom module:

vendor/magento/module-catalog-search/etc/search_request.xml  

and change line 16 in this file :

<queryReference clause="should" ref="search" /> 

To

<queryReference clause="must" ref="search" />
3
  • Before try this change the core file and check it is working , then overright this file. Commented Jul 21, 2022 at 7:05
  • Can u plz send me the complete solution like in which files i need to change Commented Jul 21, 2022 at 7:29
  • Sure i send you propere solution now Commented Jul 21, 2022 at 7:30
0

Create di.xml in this path VENDOR/Module/etc/frontend/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Elasticsearch\SearchAdapter\Query\Builder\Match"
                type="<VENDOR>\<MODULE>\SearchAdapter\Query\Builder\Match" />
</config>

Create the file : VENDOR\Module\SearchAdapter\Query\Builder\Match.php

<?php
namespace VENDOR\MODULE\SearchAdapter\Query\Builder;

use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\AttributeProvider;
use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldType\ResolverInterface as TypeResolver;
use Magento\Elasticsearch\Model\Config;
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerPool;
use Magento\Framework\Search\Request\Query\BoolExpression;
use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;
use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface;

/**
 * Extend Builder for match query. 
 * See https://magento.stackexchange.com/questions/192718/how-do-i-change-magento-2-search-from-or-logic-to-and for the full discussuon
 */
class Match extends \Magento\Elasticsearch\SearchAdapter\Query\Builder\Match
{
    /**
     * Elasticsearch condition for case when query must not appear in the matching documents.
     */
    const QUERY_CONDITION_MUST_NOT = 'must_not';

    /**
     * @var FieldMapperInterface
     */
    private $fieldMapper;

    /**
     * @var AttributeProvider
     */
    private $attributeProvider;

    /**
     * @var TypeResolver
     */
    private $fieldTypeResolver;

    /**
     * @var ValueTransformerPool
     */
    private $valueTransformerPool;
    /**
     * @var Config
     */
    private $config;

    /**
     * @param FieldMapperInterface $fieldMapper
     * @param AttributeProvider $attributeProvider
     * @param TypeResolver $fieldTypeResolver
     * @param ValueTransformerPool $valueTransformerPool
     * @param Config $config
     */
    public function __construct(
        FieldMapperInterface $fieldMapper,
        AttributeProvider $attributeProvider,
        TypeResolver $fieldTypeResolver,
        ValueTransformerPool $valueTransformerPool,
        Config $config
    ) {
        $this->fieldMapper = $fieldMapper;
        $this->attributeProvider = $attributeProvider;
        $this->fieldTypeResolver = $fieldTypeResolver;
        $this->valueTransformerPool = $valueTransformerPool;
        $this->config = $config;
        parent::__construct($fieldMapper, $attributeProvider, $fieldTypeResolver, $valueTransformerPool, $config);
    }

    /**
     * Creates valid ElasticSearch search conditions from Match queries.
     *
     * The purpose of this method is to create a structure which represents valid search query
     * for a full-text search.
     * It sets search query condition, the search query itself, and sets the search query boost.
     *
     * The search query boost is an optional in the search query and therefore it will be set to 1 by default
     * if none passed with a match query.
     *
     * @param array $matches
     * @param array $queryValue
     * @return array
     */
    protected function buildQueries(array $matches, array $queryValue)
    {
        $conditions = [];

        // Checking for quoted phrase \"phrase test\", trim escaped surrounding quotes if found
        $count = 0;
        $value = preg_replace('#^"(.*)"$#m', '$1', $queryValue['value'], -1, $count);
        $condition = ($count) ? 'match_phrase' : 'match';

        $transformedTypes = [];
        foreach ($matches as $match) {
            $resolvedField = $this->fieldMapper->getFieldName(
                $match['field'],
                ['type' => FieldMapperInterface::TYPE_QUERY]
            );

            $attributeAdapter = $this->attributeProvider->getByAttributeCode($resolvedField);
            $fieldType = $this->fieldTypeResolver->getFieldType($attributeAdapter);
            $valueTransformer = $this->valueTransformerPool->get($fieldType ?? 'text');
            $valueTransformerHash = \spl_object_hash($valueTransformer);
            if (!isset($transformedTypes[$valueTransformerHash])) {
                $transformedTypes[$valueTransformerHash] = $valueTransformer->transform($value);
            }
            $transformedValue = $transformedTypes[$valueTransformerHash];
            if (null === $transformedValue) {
                //Value is incompatible with this field type.
                continue;
            }
            $matchCondition = $match['matchCondition'] ?? $condition;

            if($matchCondition != 'match_phrase_prefix'){
                $field = [
                    'query' => $transformedValue,
                    'boost' => $match['boost'] ?? 1,
                    'operator' => 'and'
                ];
            } else {
                $field = [
                    'query' => $transformedValue,
                    'boost' => $match['boost'] ?? 1
                ];
            }
            $conditions[] = [
                'condition' => $queryValue['condition'],
                'body' => [
                    $matchCondition => [
                        $resolvedField => $field,
                    ],
                ],
            ];

        }

        return $conditions;
    }
}

And check your output.

2
  • please try this for AND logic search Commented Jul 21, 2022 at 8:39
  • Not working i am searching "FINE" and i am getting product "Driven Backpack " n magneto 2 sample data Commented Jul 21, 2022 at 10:13

Your Answer

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

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