![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/mirasvit/module-search-ultimate/src/SearchSphinx/SearchAdapter/ |
<?php /** * Mirasvit * * This source file is subject to the Mirasvit Software License, which is available at https://mirasvit.com/license/. * Do not edit or add to this file if you wish to upgrade the to newer versions in the future. * If you wish to customize this module for your needs. * Please refer to http://www.magentocommerce.com for more information. * * @category Mirasvit * @package mirasvit/module-search-ultimate * @version 2.2.35 * @copyright Copyright (C) 2024 Mirasvit (https://mirasvit.com/) */ namespace Mirasvit\SearchSphinx\SearchAdapter; use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver; use Magento\Framework\Registry; use Magento\Framework\Search\Request\Query\BoolExpression as BoolQuery; use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface; use Magento\Framework\Search\RequestInterface; use Magento\Framework\Serialize\Serializer\Json; use Mirasvit\Search\Repository\IndexRepository; use Mirasvit\Search\Service\DebugService; use Mirasvit\SearchMysql\SearchAdapter\Index\IndexNameResolver; use Mirasvit\SearchSphinx\Model\Engine; use Mirasvit\SearchSphinx\SearchAdapter\Query\Builder\MatchQuery; use Mirasvit\SearchSphinx\SearchAdapter\Query\QueryContainer; use Mirasvit\SearchSphinx\SearchAdapter\Query\QueryContainerFactory; use Mirasvit\SearchSphinx\SphinxQL\Expression as QLExpression; use Mirasvit\SearchSphinx\SphinxQL\SphinxQL; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class MapperQL { /** * @var Engine */ private $engine; /** * @var IndexScopeResolver */ private $scopeResolver; /** * @var IndexRepository */ private $indexRepository; /** * @var MatchQuery */ private $matchBuilder; /** * @var QueryContainerFactory */ private $queryContainerFactory; private $indexNameResolver; private $coreRegistry; private $serializer; public function __construct( IndexRepository $indexRepository, QueryContainerFactory $queryContainerFactory, MatchQuery $matchBuilder, IndexScopeResolver $scopeResolver, IndexNameResolver $indexNameResolver, Registry $coreRegistry, Json $serializer, Engine $engine ) { $this->queryContainerFactory = $queryContainerFactory; $this->matchBuilder = $matchBuilder; $this->indexRepository = $indexRepository; $this->scopeResolver = $scopeResolver; $this->indexNameResolver = $indexNameResolver; $this->coreRegistry = $coreRegistry; $this->serializer = $serializer; $this->engine = $engine; } /** * @param RequestInterface $request * * @return array */ public function buildQuery(RequestInterface $request) { $searchIndex = $this->indexRepository->getByIdentifier($request->getIndex()); $indexName = $this->indexNameResolver->getIndexName( $searchIndex->getIdentifier(), $request->getDimensions() ); $weights = []; foreach ($this->indexRepository->getInstance($searchIndex)->getAttributeWeights() as $attr => $weight) { if (!is_numeric(substr($attr, 0, 1))) { $weights[$attr] = pow(2, (int)$weight); } } $sphinxQuery = $this->engine->getQuery() ->select(["id", new QLExpression("weight()")]) ->from($indexName) ->limit(0, 1000000) ->option("max_matches", 1000000) ->option("field_weights", $weights) ->option("ranker", new QLExpression("expr('sum(1/min_hit_pos*user_weight + word_count*user_weight + exact_hit*user_weight*1000 + lcs*user_weight) * 1000 + bm25')")); $queryContainer = $this->queryContainerFactory->create(['request' => $request]); foreach ($request->getQuery()->getMust() as $filter) { $field = $filter->getReference()->getField(); if (method_exists($filter->getReference(), 'getFrom')) { $from = (float)$filter->getReference()->getFrom(); $to = (float)$filter->getReference()->getTo(); $sphinxQuery->where($field, 'BETWEEN', [$from, $to]); } else { if (method_exists($filter->getReference(), 'getValue')) { $value = is_array($filter->getReference()->getValue()) ? $filter->getReference()->getValue() : new QLExpression($filter->getReference()->getValue()); if (is_array($value)) { foreach ($value as $key => $option) { $value[$key] = (int)$option; } } $sphinxQuery->where($field, 'IN', is_array($value) ? $value : [$value]); } } } foreach ($request->getSort() as $sort) { $field = $sort['field']; $direction = $sort['direction']; if ($field == 'relevance') { break; } if ($field == 'name') { break; } if ($field == 'price') { $field = 'price_string'; } if ($field == 'entity_id') { $field = 'id'; } if ($field == 'position') { if ($this->coreRegistry->registry('current_category')) { $id = $this->coreRegistry->registry('current_category')->getId(); if ($id < 10000) { $field = 'position_category_' . $id; } else { $field = 'id'; } } else { $field = 'id'; } } $sphinxQuery->orderBy($field, $direction); break; } $sphinxQuery = $this->processQuery( $request->getQuery(), $sphinxQuery, BoolQuery::QUERY_CONDITION_MUST, $queryContainer ); $sphinxQuery = $this->addDerivedQueries( $queryContainer, $sphinxQuery ); $result = $sphinxQuery->execute(); DebugService::log($sphinxQuery->getCompiled(), 'search_query'); DebugService::log($this->serializer->serialize($result), 'search_results'); $pairs = []; foreach ($result as $item) { $pairs[$item['id']] = $item['weight()']; } return $pairs; } /** * @param RequestQueryInterface $query * @param SphinxQL $select * @param string $conditionType * @param QueryContainer $queryContainer * * @return SphinxQL */ private function processQuery( RequestQueryInterface $query, SphinxQL $select, $conditionType, QueryContainer $queryContainer ) { switch ($query->getType()) { case RequestQueryInterface::TYPE_MATCH: $select = $queryContainer->addMatchQuery( $select, $query, $conditionType ); break; case RequestQueryInterface::TYPE_BOOL: $select = $this->processBoolQuery( $query, $select, $queryContainer ); break; } return $select; } /** * @param BoolQuery $query * @param SphinxQL $select * @param QueryContainer $queryContainer * * @return SphinxQL */ private function processBoolQuery( BoolQuery $query, SphinxQL $select, QueryContainer $queryContainer ) { $select = $this->processBoolQueryCondition( $query->getMust(), $select, BoolQuery::QUERY_CONDITION_MUST, $queryContainer ); $select = $this->processBoolQueryCondition( $query->getShould(), $select, BoolQuery::QUERY_CONDITION_SHOULD, $queryContainer ); $select = $this->processBoolQueryCondition( $query->getMustNot(), $select, BoolQuery::QUERY_CONDITION_NOT, $queryContainer ); return $select; } /** * @param array $subQueryList * @param SphinxQL $select * @param string $conditionType * @param QueryContainer $queryContainer * * @return SphinxQL */ private function processBoolQueryCondition( array $subQueryList, SphinxQL $select, $conditionType, QueryContainer $queryContainer ) { foreach ($subQueryList as $subQuery) { $select = $this->processQuery($subQuery, $select, $conditionType, $queryContainer); } return $select; } /** * @param QueryContainer $queryContainer * @param SphinxQL $select * * @return SphinxQL */ private function addDerivedQueries( QueryContainer $queryContainer, SphinxQL $select ) { $matchQueries = $queryContainer->getMatchQueries(); if ($matchQueries) { $matchContainer = array_shift($matchQueries); $select = $this->matchBuilder->build( $select, $matchContainer->getRequest() ); } return $select; } }