Suggestions.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Elasticsearch\Model\DataProvider;
  7. use Magento\Store\Model\ScopeInterface;
  8. use Magento\Search\Model\QueryInterface;
  9. use Magento\AdvancedSearch\Model\SuggestedQueriesInterface;
  10. use Magento\Elasticsearch\Model\Config;
  11. use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
  12. use Magento\Search\Model\QueryResultFactory;
  13. use Magento\Framework\App\Config\ScopeConfigInterface;
  14. use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
  15. use Magento\Store\Model\StoreManagerInterface as StoreManager;
  16. /**
  17. * Class Suggestions
  18. */
  19. class Suggestions implements SuggestedQueriesInterface
  20. {
  21. /**
  22. * @deprecated
  23. * @see SuggestedQueriesInterface::SEARCH_SUGGESTION_COUNT
  24. */
  25. const CONFIG_SUGGESTION_COUNT = 'catalog/search/search_suggestion_count';
  26. /**
  27. * @deprecated
  28. * @see SuggestedQueriesInterface::SEARCH_SUGGESTION_COUNT_RESULTS_ENABLED
  29. */
  30. const CONFIG_SUGGESTION_COUNT_RESULTS_ENABLED = 'catalog/search/search_suggestion_count_results_enabled';
  31. /**
  32. * @deprecated
  33. * @see SuggestedQueriesInterface::SEARCH_SUGGESTION_ENABLED
  34. */
  35. const CONFIG_SUGGESTION_ENABLED = 'catalog/search/search_suggestion_enabled';
  36. /**
  37. * @var Config
  38. */
  39. private $config;
  40. /**
  41. * @var QueryResultFactory
  42. */
  43. private $queryResultFactory;
  44. /**
  45. * @var ConnectionManager
  46. */
  47. private $connectionManager;
  48. /**
  49. * @var ScopeConfigInterface
  50. */
  51. private $scopeConfig;
  52. /**
  53. * @var SearchIndexNameResolver
  54. */
  55. private $searchIndexNameResolver;
  56. /**
  57. * @var StoreManager
  58. */
  59. private $storeManager;
  60. /**
  61. * Suggestions constructor.
  62. *
  63. * @param ScopeConfigInterface $scopeConfig
  64. * @param Config $config
  65. * @param QueryResultFactory $queryResultFactory
  66. * @param ConnectionManager $connectionManager
  67. * @param SearchIndexNameResolver $searchIndexNameResolver
  68. * @param StoreManager $storeManager
  69. */
  70. public function __construct(
  71. ScopeConfigInterface $scopeConfig,
  72. Config $config,
  73. QueryResultFactory $queryResultFactory,
  74. ConnectionManager $connectionManager,
  75. SearchIndexNameResolver $searchIndexNameResolver,
  76. StoreManager $storeManager
  77. ) {
  78. $this->queryResultFactory = $queryResultFactory;
  79. $this->connectionManager = $connectionManager;
  80. $this->scopeConfig = $scopeConfig;
  81. $this->config = $config;
  82. $this->searchIndexNameResolver = $searchIndexNameResolver;
  83. $this->storeManager = $storeManager;
  84. }
  85. /**
  86. * @inheritdoc
  87. */
  88. public function getItems(QueryInterface $query)
  89. {
  90. $result = [];
  91. if ($this->isSuggestionsAllowed()) {
  92. $isResultsCountEnabled = $this->isResultsCountEnabled();
  93. foreach ($this->getSuggestions($query) as $suggestion) {
  94. $count = null;
  95. if ($isResultsCountEnabled) {
  96. $count = isset($suggestion['freq']) ? $suggestion['freq'] : null;
  97. }
  98. $result[] = $this->queryResultFactory->create(
  99. [
  100. 'queryText' => $suggestion['text'],
  101. 'resultsCount' => $count,
  102. ]
  103. );
  104. }
  105. }
  106. return $result;
  107. }
  108. /**
  109. * @inheritdoc
  110. */
  111. public function isResultsCountEnabled()
  112. {
  113. return $this->scopeConfig->isSetFlag(
  114. self::CONFIG_SUGGESTION_COUNT_RESULTS_ENABLED,
  115. ScopeInterface::SCOPE_STORE
  116. );
  117. }
  118. /**
  119. * Get Suggestions
  120. *
  121. * @param QueryInterface $query
  122. *
  123. * @return array
  124. * @throws \Magento\Framework\Exception\NoSuchEntityException
  125. */
  126. private function getSuggestions(QueryInterface $query)
  127. {
  128. $suggestions = [];
  129. $searchSuggestionsCount = $this->getSearchSuggestionsCount();
  130. $suggestRequest = [
  131. 'index' => $this->searchIndexNameResolver->getIndexName(
  132. $this->storeManager->getStore()->getId(),
  133. Config::ELASTICSEARCH_TYPE_DEFAULT
  134. ),
  135. 'body' => [
  136. 'suggestions' => [
  137. 'text' => $query->getQueryText(),
  138. 'phrase' => [
  139. 'field' => '_all',
  140. 'analyzer' => 'standard',
  141. 'size' => $searchSuggestionsCount,
  142. 'max_errors' => 2,
  143. 'direct_generator' => [
  144. [
  145. 'field' => '_all',
  146. 'min_word_length' => 3,
  147. 'min_doc_freq' => 1
  148. ]
  149. ],
  150. ]
  151. ]
  152. ]
  153. ];
  154. $result = $this->fetchQuery($suggestRequest);
  155. if (is_array($result)) {
  156. foreach ($result['suggestions'] as $token) {
  157. foreach ($token['options'] as $key => $suggestion) {
  158. $suggestions[$suggestion['score'] . '_' . $key] = $suggestion;
  159. }
  160. }
  161. ksort($suggestions);
  162. $suggestions = array_slice($suggestions, 0, $searchSuggestionsCount);
  163. }
  164. return $suggestions;
  165. }
  166. /**
  167. * Fetch Query
  168. *
  169. * @param array $query
  170. * @return array
  171. */
  172. private function fetchQuery(array $query)
  173. {
  174. return $this->connectionManager->getConnection()->suggest($query);
  175. }
  176. /**
  177. * Get search suggestions Max Count from config
  178. *
  179. * @return int
  180. */
  181. private function getSearchSuggestionsCount()
  182. {
  183. return (int)$this->scopeConfig->getValue(
  184. self::CONFIG_SUGGESTION_COUNT,
  185. ScopeInterface::SCOPE_STORE
  186. );
  187. }
  188. /**
  189. * Is Search Suggestions Allowed
  190. *
  191. * @return bool
  192. */
  193. private function isSuggestionsAllowed()
  194. {
  195. $isSuggestionsEnabled = $this->scopeConfig->isSetFlag(
  196. self::CONFIG_SUGGESTION_ENABLED,
  197. ScopeInterface::SCOPE_STORE
  198. );
  199. $isEnabled = $this->config->isElasticsearchEnabled();
  200. $isSuggestionsAllowed = ($isEnabled && $isSuggestionsEnabled);
  201. return $isSuggestionsAllowed;
  202. }
  203. }