123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Elasticsearch6\Model\DataProvider;
- use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProviderInterface;
- use Magento\Store\Model\ScopeInterface;
- use Magento\Search\Model\QueryInterface;
- use Magento\AdvancedSearch\Model\SuggestedQueriesInterface;
- use Magento\Elasticsearch\Model\Config;
- use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
- use Magento\Search\Model\QueryResultFactory;
- use Magento\Framework\App\Config\ScopeConfigInterface;
- use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
- use Magento\Store\Model\StoreManagerInterface as StoreManager;
- /**
- * Class Suggestions
- */
- class Suggestions implements SuggestedQueriesInterface
- {
- /**
- * @var Config
- */
- private $config;
- /**
- * @var QueryResultFactory
- */
- private $queryResultFactory;
- /**
- * @var ConnectionManager
- */
- private $connectionManager;
- /**
- * @var ScopeConfigInterface
- */
- private $scopeConfig;
- /**
- * @var SearchIndexNameResolver
- */
- private $searchIndexNameResolver;
- /**
- * @var StoreManager
- */
- private $storeManager;
- /**
- * @var FieldProviderInterface
- */
- private $fieldProvider;
- /**
- * Suggestions constructor.
- *
- * @param ScopeConfigInterface $scopeConfig
- * @param Config $config
- * @param QueryResultFactory $queryResultFactory
- * @param ConnectionManager $connectionManager
- * @param SearchIndexNameResolver $searchIndexNameResolver
- * @param StoreManager $storeManager
- * @param FieldProviderInterface $fieldProvider
- */
- public function __construct(
- ScopeConfigInterface $scopeConfig,
- Config $config,
- QueryResultFactory $queryResultFactory,
- ConnectionManager $connectionManager,
- SearchIndexNameResolver $searchIndexNameResolver,
- StoreManager $storeManager,
- FieldProviderInterface $fieldProvider
- ) {
- $this->queryResultFactory = $queryResultFactory;
- $this->connectionManager = $connectionManager;
- $this->scopeConfig = $scopeConfig;
- $this->config = $config;
- $this->searchIndexNameResolver = $searchIndexNameResolver;
- $this->storeManager = $storeManager;
- $this->fieldProvider = $fieldProvider;
- }
- /**
- * @inheritdoc
- */
- public function getItems(QueryInterface $query)
- {
- $result = [];
- if ($this->isSuggestionsAllowed()) {
- $isResultsCountEnabled = $this->isResultsCountEnabled();
- foreach ($this->getSuggestions($query) as $suggestion) {
- $count = null;
- if ($isResultsCountEnabled) {
- $count = isset($suggestion['freq']) ? $suggestion['freq'] : null;
- }
- $result[] = $this->queryResultFactory->create(
- [
- 'queryText' => $suggestion['text'],
- 'resultsCount' => $count,
- ]
- );
- }
- }
- return $result;
- }
- /**
- * @inheritdoc
- */
- public function isResultsCountEnabled()
- {
- return $this->scopeConfig->isSetFlag(
- SuggestedQueriesInterface::SEARCH_SUGGESTION_COUNT_RESULTS_ENABLED,
- ScopeInterface::SCOPE_STORE
- );
- }
- /**
- * Get Suggestions
- *
- * @param QueryInterface $query
- *
- * @return array
- * @throws \Magento\Framework\Exception\NoSuchEntityException
- */
- private function getSuggestions(QueryInterface $query)
- {
- $suggestions = [];
- $searchSuggestionsCount = $this->getSearchSuggestionsCount();
- $searchQuery = $this->initQuery($query);
- $searchQuery = $this->addSuggestFields($searchQuery, $searchSuggestionsCount);
- $result = $this->fetchQuery($searchQuery);
- if (is_array($result)) {
- foreach ($result['suggest'] ?? [] as $suggest) {
- foreach ($suggest as $token) {
- foreach ($token['options'] ?? [] as $key => $suggestion) {
- $suggestions[$suggestion['score'] . '_' . $key] = $suggestion;
- }
- }
- }
- ksort($suggestions);
- $texts = array_unique(array_column($suggestions, 'text'));
- $suggestions = array_slice(
- array_intersect_key(array_values($suggestions), $texts),
- 0,
- $searchSuggestionsCount
- );
- }
- return $suggestions;
- }
- /**
- * Init Search Query
- *
- * @param string $query
- *
- * @return array
- * @throws \Magento\Framework\Exception\NoSuchEntityException
- */
- private function initQuery($query)
- {
- $searchQuery = [
- 'index' => $this->searchIndexNameResolver->getIndexName(
- $this->storeManager->getStore()->getId(),
- Config::ELASTICSEARCH_TYPE_DEFAULT
- ),
- 'type' => Config::ELASTICSEARCH_TYPE_DEFAULT,
- 'body' => [
- 'suggest' => [
- 'text' => $query->getQueryText()
- ]
- ],
- ];
- return $searchQuery;
- }
- /**
- * Build Suggest on searchable fields.
- *
- * @param array $searchQuery
- * @param int $searchSuggestionsCount
- *
- * @return array
- */
- private function addSuggestFields($searchQuery, $searchSuggestionsCount)
- {
- $fields = $this->getSuggestFields();
- foreach ($fields as $field) {
- $searchQuery['body']['suggest']['phrase_' . $field] = [
- 'phrase' => [
- 'field' => $field,
- 'analyzer' => 'standard',
- 'size' => $searchSuggestionsCount,
- 'max_errors' => 1,
- 'direct_generator' => [
- [
- 'field' => $field,
- 'min_word_length' => 3,
- 'min_doc_freq' => 1,
- ]
- ],
- ],
- ];
- }
- return $searchQuery;
- }
- /**
- * Get fields to build suggest query on.
- *
- * @return array
- */
- private function getSuggestFields()
- {
- $fields = array_filter($this->fieldProvider->getFields(), function ($field) {
- return (($field['type'] ?? null) === 'text') && (($field['index'] ?? null) !== false);
- });
- return array_keys($fields);
- }
- /**
- * Fetch Query
- *
- * @param array $query
- * @return array
- */
- private function fetchQuery(array $query)
- {
- return $this->connectionManager->getConnection()->query($query);
- }
- /**
- * Get search suggestions Max Count from config
- *
- * @return int
- */
- private function getSearchSuggestionsCount()
- {
- return (int) $this->scopeConfig->getValue(
- SuggestedQueriesInterface::SEARCH_SUGGESTION_COUNT,
- ScopeInterface::SCOPE_STORE
- );
- }
- /**
- * Is Search Suggestions Allowed
- *
- * @return bool
- */
- private function isSuggestionsAllowed()
- {
- $isSuggestionsEnabled = $this->scopeConfig->isSetFlag(
- SuggestedQueriesInterface::SEARCH_SUGGESTION_ENABLED,
- ScopeInterface::SCOPE_STORE
- );
- $isEnabled = $this->config->isElasticsearchEnabled();
- $isSuggestionsAllowed = ($isEnabled && $isSuggestionsEnabled);
- return $isSuggestionsAllowed;
- }
- }
|