/** * @param RequestInterface $request * @return \Magento\Framework\DB\Ddl\Table * @throws \Exception */ public function buildQuery(RequestInterface $request) { $searchIndex = $this->indexFactory->create()->load($request->getIndex()); $weights = []; foreach ($searchIndex->getIndexInstance()->getAttributeWeights() as $attr => $weight) { $weights[$attr] = pow(2, $weight); } $indexName = $this->scopeResolver->resolve($request->getIndex(), $request->getDimensions()); $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(word_count*user_weight) + bm25')")); //@todo http://habrahabr.ru/company/sphinx/blog/133790/ $queryContainer = $this->queryContainerFactory->create(['request' => $request]); $sphinxQuery = $this->processQuery($request->getQuery(), $sphinxQuery, BoolQuery::QUERY_CONDITION_MUST, $queryContainer); $sphinxQuery = $this->addDerivedQueries($queryContainer, $sphinxQuery); $result = $sphinxQuery->execute(); if (isset($_GET) && isset($_GET['debug'])) { echo $sphinxQuery->getCompiled(); echo '<pre>' . print_r($result, true) . '</pre>'; } $documents = []; foreach ($result as $item) { $document = $this->documentFactory->create([]); $document->setId($item['id'])->setCustomAttribute('entity_id', $item['id'])->setCustomAttribute('score', new DataObject(['value' => $item['weight()']])); $documents[] = $document; } $table = $this->temporaryStorage->storeApiDocuments($documents); return $table; }
/** * Build index query * * @param RequestInterface $request * @return Select */ public function build(RequestInterface $request) { $select = $this->getSelect()->from(['search_index' => $this->resource->getTableName($request->getIndex())], ['entity_id' => 'search_index.product_id'])->joinLeft(['category_index' => $this->resource->getTableName('catalog_category_product_index')], 'search_index.product_id = category_index.product_id' . ' AND search_index.store_id = category_index.store_id', []); $isShowOutOfStock = $this->config->isSetFlag('cataloginventory/options/show_out_of_stock', ScopeInterface::SCOPE_STORE); if ($isShowOutOfStock === false) { $select->joinLeft(['stock_index' => $this->resource->getTableName('cataloginventory_stock_status')], 'search_index.product_id = stock_index.product_id' . $this->getReadConnection()->quoteInto(' AND stock_index.website_id = ?', $this->storeManager->getWebsite()->getId()), [])->where('stock_index.stock_status = ?', 1); } return $select; }
/** * @param RequestInterface $request * @param Table $documentsTable * @return array */ private function processAggregations(RequestInterface $request, Table $documentsTable) { $aggregations = []; $buckets = $request->getAggregation(); $dataProvider = $this->dataProviderContainer->get($request->getIndex()); foreach ($buckets as $bucket) { $aggregationBuilder = $this->aggregationContainer->get($bucket->getType()); $aggregations[$bucket->getName()] = $aggregationBuilder->build($dataProvider, $request->getDimensions(), $bucket, $documentsTable); } return $aggregations; }
/** * Build index query * * @param RequestInterface $request * @return Select */ public function build(RequestInterface $request) { $searchIndexTable = $this->scopeResolver->resolve($request->getIndex(), $request->getDimensions()); $select = $this->resource->getConnection()->select()->from(['search_index' => $searchIndexTable], ['entity_id' => 'entity_id'])->joinLeft(['cea' => $this->resource->getTableName('catalog_eav_attribute')], 'search_index.attribute_id = cea.attribute_id', []); $select = $this->tableMapper->addTables($select, $request); $select = $this->processDimensions($request, $select); $isShowOutOfStock = $this->config->isSetFlag('cataloginventory/options/show_out_of_stock', ScopeInterface::SCOPE_STORE); if ($isShowOutOfStock === false) { $select->joinLeft(['stock_index' => $this->resource->getTableName('cataloginventory_stock_status')], 'search_index.entity_id = stock_index.product_id' . $this->resource->getConnection()->quoteInto(' AND stock_index.website_id = ?', $this->storeManager->getWebsite()->getId()), []); $select->where('stock_index.stock_status = ?', 1); } return $select; }
/** * Build adapter dependent query * * @param RequestInterface $request * @throws \Exception * @return Select */ public function buildQuery(RequestInterface $request) { if (!isset($this->indexProviders[$request->getIndex()])) { throw new \Exception('Index provider not configured'); } $select = $this->indexProviders[$request->getIndex()]->build($request); /** @var ScoreBuilder $scoreBuilder */ $scoreBuilder = $this->scoreBuilderFactory->create(); $select = $this->processQuery($scoreBuilder, $request->getQuery(), $select, BoolQuery::QUERY_CONDITION_MUST); $select = $this->processDimensions($request, $select); $select->columns($scoreBuilder->build()); $select->order($scoreBuilder->getScoreAlias() . ' ' . Select::SQL_DESC); return $select; }
/** * Execute the search request with ES. * * @param RequestInterface $request Search request. * * @return array */ private function doSearch(RequestInterface $request) { $searchRequest = ['index' => $request->getIndex(), 'type' => $request->getType(), 'body' => $this->requestMapper->buildSearchRequest($request)]; return $this->client->search($searchRequest); }
/** * {@inheritdoc} */ public function resolve(RequestInterface $request, array $documentIds) { $aggregations = isset($this->resolvers[$request->getIndex()]) ? $this->resolvers[$request->getIndex()]->resolve($request, $documentIds) : $request->getAggregation(); return $aggregations; }
/** * Build adapter dependent query * * @param RequestInterface $request * @throws \Exception * @return Select */ public function buildQuery(RequestInterface $request) { if (!isset($this->indexProviders[$request->getIndex()])) { throw new \Exception('Index provider not configured'); } $indexBuilder = $this->indexProviders[$request->getIndex()]; $queryContainer = $this->queryContainerFactory->create( [ 'indexBuilder' => $indexBuilder, 'request' => $request ] ); $select = $indexBuilder->build($request); /** @var ScoreBuilder $scoreBuilder */ $scoreBuilder = $this->scoreBuilderFactory->create(); $select = $this->processQuery( $scoreBuilder, $request->getQuery(), $select, BoolQuery::QUERY_CONDITION_MUST, $queryContainer ); $filtersCount = $queryContainer->getFiltersCount(); if ($filtersCount > 1) { $select->group('entity_id'); $select->having('COUNT(DISTINCT search_index.attribute_id) = ' . $filtersCount); } $select = $this->addMatchQueries( $request, $queryContainer->getDerivedQueries(), $scoreBuilder, $select, $indexBuilder ); $select->limit($request->getSize()); $select->order('relevance ' . Select::SQL_DESC); return $select; }
/** * Build adapter dependent query * * @param RequestInterface $request * @throws \Exception * @return Select */ public function buildQuery(RequestInterface $request) { if (!isset($this->indexProviders[$request->getIndex()])) { throw new \Exception('Index provider not configured'); } $indexBuilder = $this->indexProviders[$request->getIndex()]; $queryContainer = $this->queryContainerFactory->create( [ 'indexBuilder' => $indexBuilder, 'request' => $request ] ); $select = $indexBuilder->build($request); /** @var ScoreBuilder $scoreBuilder */ $scoreBuilder = $this->scoreBuilderFactory->create(); $select = $this->processQuery( $scoreBuilder, $request->getQuery(), $select, BoolQuery::QUERY_CONDITION_MUST, $queryContainer ); $select = $this->processDimensions($request, $select); $select->columns($scoreBuilder->build()); $select->limit(self::SQL_ENTITIES_LIMIT); $filtersCount = $queryContainer->getFiltersCount(); if ($filtersCount > 1) { $select->group('entity_id'); $select->having('COUNT(DISTINCT search_index.attribute_id) = ' . $filtersCount); } $select = $this->createAroundSelect($select, $scoreBuilder); $select->limit($request->getSize()); $matchQueries = $queryContainer->getDerivedQueries(); if ($matchQueries) { $subSelect = $select; $select = $this->resource->getConnection(Resource::DEFAULT_READ_RESOURCE)->select(); $tables = array_merge($queryContainer->getDerivedQueryNames(), ['main_select.relevance']); $relevance = implode('.relevance + ', $tables); $select ->from( ['main_select' => $subSelect], [ $this->entityMetadata->getEntityId() => 'entity_id', 'relevance' => sprintf('(%s)', $relevance), ] ); foreach ($matchQueries as $matchName => $matchSelect) { $select->join( [$matchName => $this->createAroundSelect($matchSelect, $scoreBuilder)], $matchName . '.entity_id = main_select.entity_id', [] ); } } $select->order('relevance ' . Select::SQL_DESC); return $select; }
/** * Build adapter dependent query * * @param RequestInterface $request * @throws \LogicException * @return Select */ public function buildQuery(RequestInterface $request) { if (!array_key_exists($request->getIndex(), $this->indexProviders)) { throw new \LogicException('Index provider not configured'); } $indexBuilder = $this->indexProviders[$request->getIndex()]; $queryContainer = $this->queryContainerFactory->create(['indexBuilder' => $indexBuilder, 'request' => $request]); $select = $indexBuilder->build($request); /** @var ScoreBuilder $scoreBuilder */ $scoreBuilder = $this->scoreBuilderFactory->create(); $select = $this->processQuery($scoreBuilder, $request->getQuery(), $select, BoolQuery::QUERY_CONDITION_MUST, $queryContainer); $select = $this->addDerivedQueries($request, $queryContainer, $scoreBuilder, $select, $indexBuilder); $select->limit($request->getSize()); $select->order('relevance ' . Select::SQL_DESC); return $select; }
/** * {@inheritdoc} */ public function build(RequestInterface $request) { $searchIndexTable = $this->scopeResolver->resolve($request->getIndex(), $request->getDimensions()); $select = $this->getSelect()->from(['search_index' => $searchIndexTable], ['entity_id' => 'entity_id'])->joinLeft(['tmp' => new \Zend_Db_Expr('(SELECT 1 as search_weight)')], '1=1', ''); return $select; }