Skip to content

Commit

Permalink
Fix search suggestions (#110)
Browse files Browse the repository at this point in the history
* Bugfix: autocomplete suggests nonsearchable terms (#102)

* added additional check to ensure autocomplete suggests only searchable terms

---------

Co-authored-by: Ryan Sun <[email protected]>

* Update unit test for autocomplete suggests fix (#104)

* added additional check to ensure autocomplete suggests only searchable terms

* updated unitest for search suggest fix

* added type casting for isSuggestible

* reverted suggestible flag and fixed getSuggestFields method

* updated suggest contructor params to avoid bic

* updated unit test with new dependency productAttributeCollectionFactory for Suggestions

* add fieldProvider back to Suggestions constructor

---------

Co-authored-by: Ryan Sun <[email protected]>

---------

Co-authored-by: Ryan Sun <[email protected]>
Co-authored-by: Ryan Sun <[email protected]>
  • Loading branch information
3 people authored Oct 30, 2024
1 parent 2f768ca commit 7fc2e31
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
use Exception;
use Magento\AdvancedSearch\Model\SuggestedQueriesInterface;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProviderInterface;
use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;
use Magento\Elasticsearch\Model\Config;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
Expand Down Expand Up @@ -61,6 +63,16 @@ class Suggestions implements SuggestedQueriesInterface
*/
private $fieldProvider;

/**
* @var CollectionFactory
*/
private $productAttributeCollectionFactory;

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

/**
* @var LoggerInterface
*/
Expand Down Expand Up @@ -90,6 +102,8 @@ class Suggestions implements SuggestedQueriesInterface
* @param FieldProviderInterface $fieldProvider
* @param LoggerInterface|null $logger
* @param GetSuggestionFrequencyInterface|null $getSuggestionFrequency
* @param CollectionFactory|null $productAttributeCollectionFactory
* @param FieldMapperInterface|null $fieldMapper
* @param array $responseErrorExceptionList
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
Expand All @@ -103,6 +117,8 @@ public function __construct(
FieldProviderInterface $fieldProvider,
LoggerInterface $logger = null,
?GetSuggestionFrequencyInterface $getSuggestionFrequency = null,
?CollectionFactory $productAttributeCollectionFactory = null,
?FieldMapperInterface $fieldMapper = null,
array $responseErrorExceptionList = []
) {
$this->queryResultFactory = $queryResultFactory;
Expand All @@ -111,10 +127,13 @@ public function __construct(
$this->config = $config;
$this->searchIndexNameResolver = $searchIndexNameResolver;
$this->storeManager = $storeManager;
$this->fieldProvider = $fieldProvider;
$this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
$this->getSuggestionFrequency = $getSuggestionFrequency ?:
ObjectManager::getInstance()->get(GetSuggestionFrequencyInterface::class);
$this->productAttributeCollectionFactory = $productAttributeCollectionFactory ?:
ObjectManager::getInstance()->get(CollectionFactory::class);
$this->fieldMapper = $fieldMapper ?:
ObjectManager::getInstance()->get(FieldMapperInterface::class);
$this->responseErrorExceptionList = array_merge($this->responseErrorExceptionList, $responseErrorExceptionList);
}

Expand Down Expand Up @@ -281,11 +300,20 @@ private function addSuggestFields($searchQuery, $searchSuggestionsCount)
*/
private function getSuggestFields()
{
$fields = array_filter($this->fieldProvider->getFields(), function ($field) {
return (($field['type'] ?? null) === 'text') && (($field['index'] ?? null) !== false);
});

return array_keys($fields);
$productAttributes = $this->productAttributeCollectionFactory->create();
$productAttributes->addFieldToFilter(
'is_searchable',
1
);
$attributeCodes = $productAttributes->getColumnValues('attribute_code');
$fields = [];
foreach ($attributeCodes as $attributeCode) {
$fields[] = $this->fieldMapper->getFieldName(
$attributeCode,
['type' => FieldMapperInterface::TYPE_QUERY]
);
}
return $fields;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
use Magento\Search\Model\QueryInterface;
use Magento\Search\Model\QueryResult;
use Magento\Search\Model\QueryResultFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection as ProductAttributeCollection;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface as StoreManager;
use PHPUnit\Framework\MockObject\MockObject;
Expand Down Expand Up @@ -85,6 +87,11 @@ class SuggestionsTest extends TestCase
*/
private $query;

/**
* @var CollectionFactory|MockObject
*/
private $productAttributeCollectionFactory;

/**
* Set up test environment
*
Expand Down Expand Up @@ -137,6 +144,11 @@ protected function setUp(): void
->disableOriginalConstructor()
->getMockForAbstractClass();

$this->productAttributeCollectionFactory = $this->getMockBuilder(CollectionFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->getMock();

$objectManager = new ObjectManagerHelper($this);

$this->model = $objectManager->getObject(
Expand All @@ -150,6 +162,7 @@ protected function setUp(): void
'storeManager' => $this->storeManager,
'fieldProvider' => $this->fieldProvider,
'logger' => $this->logger,
'productAttributeCollectionFactory' => $this->productAttributeCollectionFactory,
]
);
}
Expand Down Expand Up @@ -177,6 +190,9 @@ public function testGetItemsWithDisabledSearchSuggestion(): void
$this->queryResultFactory->expects($this->never())
->method('create');

$this->productAttributeCollectionFactory->expects($this->never())
->method('create');

$this->assertEmpty($this->model->getItems($this->query));
}

Expand Down Expand Up @@ -216,6 +232,21 @@ public function testGetItemsWithEnabledSearchSuggestion(): void
->method('create')
->willReturn($query);

$objectManager = new ObjectManagerHelper($this);
$productAttributeCollection = $objectManager->getCollectionMock(ProductAttributeCollection::class, []);

$productAttributeCollection->expects($this->once())
->method('addFieldToFilter')
->willReturnSelf();

$productAttributeCollection->expects($this->once())
->method('getColumnValues')
->willReturn([]);

$this->productAttributeCollectionFactory->expects($this->once())
->method('create')
->willReturn($productAttributeCollection);

$this->assertEquals([$query], $this->model->getItems($this->query));
}

Expand Down Expand Up @@ -243,6 +274,21 @@ public function testGetItemsException(): void
$this->queryResultFactory->expects($this->never())
->method('create');

$objectManager = new ObjectManagerHelper($this);
$productAttributeCollection = $objectManager->getCollectionMock(ProductAttributeCollection::class, []);

$productAttributeCollection->expects($this->once())
->method('addFieldToFilter')
->willReturnSelf();

$productAttributeCollection->expects($this->once())
->method('getColumnValues')
->willReturn([]);

$this->productAttributeCollectionFactory->expects($this->once())
->method('create')
->willReturn($productAttributeCollection);

$this->assertEmpty($this->model->getItems($this->query));
}

Expand Down Expand Up @@ -287,10 +333,6 @@ private function prepareSearchQuery(): void
->method('getQueryText')
->willReturn('query');

$this->fieldProvider->expects($this->once())
->method('getFields')
->willReturn([]);

$this->connectionManager->expects($this->once())
->method('getConnection')
->willReturn($this->client);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Magento\OpenSearch\Model\SearchClient;
use Magento\Search\Model\QueryInterface;
use Magento\Search\Model\QueryResultFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection as ProductAttributeCollection;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface as StoreManager;
use OpenSearch\Common\Exceptions\BadRequest400Exception;
Expand Down Expand Up @@ -84,6 +86,11 @@ class SuggestionsTest extends TestCase
*/
private $query;

/**
* @var CollectionFactory|MockObject
*/
private $productAttributeCollectionFactory;

/**
* Set up test environment
*
Expand Down Expand Up @@ -136,6 +143,11 @@ protected function setUp(): void
->disableOriginalConstructor()
->getMockForAbstractClass();

$this->productAttributeCollectionFactory = $this->getMockBuilder(CollectionFactory::class)
->disableOriginalConstructor()
->onlyMethods(['create'])
->getMock();

$objectManager = new ObjectManagerHelper($this);

$this->model = $objectManager->getObject(
Expand All @@ -149,6 +161,7 @@ protected function setUp(): void
'storeManager' => $this->storeManager,
'fieldProvider' => $this->fieldProvider,
'logger' => $this->logger,
'productAttributeCollectionFactory' => $this->productAttributeCollectionFactory,
'responseErrorExceptionList' => ['opensearchBadRequest400' => BadRequest400Exception::class]
]
);
Expand All @@ -175,6 +188,21 @@ public function testGetItemsException(): void
$this->queryResultFactory->expects($this->never())
->method('create');

$objectManager = new ObjectManagerHelper($this);
$productAttributeCollection = $objectManager->getCollectionMock(ProductAttributeCollection::class, []);

$productAttributeCollection->expects($this->once())
->method('addFieldToFilter')
->willReturnSelf();

$productAttributeCollection->expects($this->once())
->method('getColumnValues')
->willReturn([]);

$this->productAttributeCollectionFactory->expects($this->once())
->method('create')
->willReturn($productAttributeCollection);

$this->assertEmpty($this->model->getItems($this->query));
}

Expand Down Expand Up @@ -219,10 +247,6 @@ private function prepareSearchQuery(): void
->method('getQueryText')
->willReturn('query');

$this->fieldProvider->expects($this->once())
->method('getFields')
->willReturn([]);

$this->connectionManager->expects($this->once())
->method('getConnection')
->willReturn($this->client);
Expand Down

0 comments on commit 7fc2e31

Please sign in to comment.