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
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" />
-
Before try this change the core file and check it is working , then overright this file. Jul 21, 2022 at 7:05
-
Can u plz send me the complete solution like in which files i need to change Jul 21, 2022 at 7:29
-
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.
-
-
Not working i am searching "FINE" and i am getting product "Driven Backpack " n magneto 2 sample data Jul 21, 2022 at 10:13