public function buildQuery(RequestInterface $request) { // $params = new Object(); $params = $this->searchHelper->getSearchParams(); $this->processQuery($request->getQuery(), $params, BoolQuery::QUERY_CONDITION_MUST); return $params; }
/** * @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; }
public function testResolveWithoutSpecificResolver() { $aggregations = ['aggregation_1']; $this->request->expects($this->atLeastOnce())->method('getIndex')->willReturn('index_1'); $this->request->expects($this->once())->method('getAggregation')->willReturn($aggregations); $this->assertEquals($aggregations, $this->aggregationResolver->resolve($this->request, [])); }
public function testResolve() { $documentIds = [1, 2, 3]; $attributeSetIds = [4, 5]; $requestName = 'request_name'; $this->attributeSetFinder->expects($this->once())->method('findAttributeSetIdsByProductIds')->with($documentIds)->willReturn($attributeSetIds); $searchCriteria = $this->getMock(SearchCriteriaInterface::class); $this->searchCriteriaBuilder->expects($this->once())->method('addFilter')->with('attribute_set_id', $attributeSetIds, 'in')->willReturnSelf(); $this->searchCriteriaBuilder->expects($this->once())->method('create')->willReturn($searchCriteria); $attributeFirst = $this->getMock(ProductAttributeInterface::class); $attributeFirst->expects($this->once())->method('getAttributeCode')->willReturn('code_1'); $attributeSecond = $this->getMock(ProductAttributeInterface::class); $attributeSecond->expects($this->once())->method('getAttributeCode')->willReturn('code_2'); $searchResult = $this->getMock(ProductAttributeSearchResultsInterface::class); $searchResult->expects($this->once())->method('getItems')->willReturn([$attributeFirst, $attributeSecond]); $this->productAttributeRepository->expects($this->once())->method('getList')->with($searchCriteria)->willReturn($searchResult); $bucketFirst = $this->getMock(BucketInterface::class); $bucketFirst->expects($this->once())->method('getField')->willReturn('code_1'); $bucketSecond = $this->getMock(BucketInterface::class); $bucketSecond->expects($this->once())->method('getField')->willReturn('some_another_code'); $bucketThird = $this->getMock(BucketInterface::class); $bucketThird->expects($this->once())->method('getName')->willReturn('custom_not_attribute_field'); $this->request->expects($this->once())->method('getAggregation')->willReturn([$bucketFirst, $bucketSecond, $bucketThird]); $this->request->expects($this->once())->method('getName')->willReturn($requestName); $this->config->expects($this->once())->method('get')->with($requestName)->willReturn(['aggregations' => ['custom_not_attribute_field' => []]]); $this->assertEquals([$bucketFirst, $bucketThird], $this->aggregationResolver->resolve($this->request, $documentIds)); }
/** * 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; }
/** * {@inheritdoc} */ public function resolve(RequestInterface $request, array $documentIds) { $data = $this->config->get($request->getName()); $bucketKeys = isset($data['aggregations']) ? array_keys($data['aggregations']) : []; $attributeCodes = $this->getApplicableAttributeCodes($documentIds); $resolvedAggregation = array_filter($request->getAggregation(), function ($bucket) use($attributeCodes, $bucketKeys) { /** @var BucketInterface $bucket */ return in_array($bucket->getField(), $attributeCodes) || in_array($bucket->getName(), $bucketKeys); }); return array_values($resolvedAggregation); }
/** * @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; }
protected function mockBuild($index, $tableSuffix) { $this->request->expects($this->once())->method('getIndex')->will($this->returnValue($index)); $this->resource->expects($this->any())->method('getTableName')->will($this->returnCallback(function ($index) { return is_array($index) ? $index[0] . $index[1] : $index; })); $this->select->expects($this->once())->method('from')->with(['search_index' => $index . $tableSuffix], ['entity_id' => 'product_id'])->will($this->returnSelf()); $this->select->expects($this->at(1))->method('joinLeft')->with(['category_index' => 'catalog_category_product_index'], 'search_index.product_id = category_index.product_id' . ' AND search_index.store_id = category_index.store_id', [])->will($this->returnSelf()); $this->select->expects($this->at(2))->method('joinLeft')->with(['cea' => 'catalog_eav_attribute'], 'search_index.attribute_id = cea.attribute_id', ['search_weight'])->will($this->returnSelf()); $this->select->expects($this->at(3))->method('joinLeft')->with(['cpie' => $this->resource->getTableName('catalog_product_index_eav')], 'search_index.product_id = cpie.entity_id AND search_index.attribute_id = cpie.attribute_id', [])->willReturnSelf(); }
/** * Test for method "build" */ public function testBuild() { $fetchResult = ['name' => ['some', 'result']]; $documents = [['product_id' => 1, 'sku' => 'Product']]; $this->bucket->expects($this->once())->method('getName')->willReturn('name'); $this->entityMetadata->expects($this->once())->method('getEntityId')->willReturn('product_id'); $this->request->expects($this->once())->method('getAggregation')->willReturn([$this->bucket]); $this->request->expects($this->once())->method('getDimensions')->willReturn([]); $this->bucketBuilder->expects($this->once())->method('build')->willReturn($fetchResult['name']); $result = $this->builder->build($this->request, $documents); $this->assertEquals($result, $fetchResult); }
/** * @param Select $select * @param RequestInterface $request * @return Select */ public function addTables(Select $select, RequestInterface $request) { $mappedTables = []; $filters = $this->getFilters($request->getQuery()); foreach ($filters as $filter) { list($alias, $table, $mapOn, $mappedFields) = $this->getMappingData($filter); if (!array_key_exists($alias, $mappedTables)) { $select->joinLeft([$alias => $table], $mapOn, $mappedFields); $mappedTables[$alias] = $table; } } return $select; }
/** * @param Select $select * @param RequestQueryInterface $query * @param string $conditionType * @return Select */ public function addMatchQuery( Select $select, RequestQueryInterface $query, $conditionType ) { $subSelect = $this->createSelect(); $subScoreBuilder = $this->scoreBuilderFactory->create(); $this->buildMatchQuery($subScoreBuilder, $subSelect, $query, $conditionType); $subSelect->columns($subScoreBuilder->build()); $subSelect->limit($this->request->getSize()); $this->addDerivedQuery($subSelect); return $select; }
/** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Unknown query type 'unknownQuery' */ public function testGetUnknownQueryType() { $query = $this->getMockBuilder('Magento\\Framework\\Search\\Request\\QueryInterface')->setMethods(['getType'])->disableOriginalConstructor()->getMockForAbstractClass(); $query->expects($this->exactly(2))->method('getType')->will($this->returnValue('unknownQuery')); $this->request->expects($this->once())->method('getQuery')->will($this->returnValue($query)); $this->mapper->buildQuery($this->request); }
private function createMatchQuery() { $this->request->expects($this->once())->method('getDimensions')->will($this->returnValue([$this->createDimension()])); $this->dimensionsBuilder->expects($this->once())->method('build')->will($this->returnValue('a = b')); $query = $this->getMockBuilder('Magento\\Framework\\Search\\Request\\Query\\Match')->setMethods(['getType'])->disableOriginalConstructor()->getMockForAbstractClass(); $query->expects($this->once())->method('getType')->will($this->returnValue(QueryInterface::TYPE_MATCH)); return $query; }
/** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Unknown query type 'unknownQuery' */ public function testGetUnknownQueryType() { $select = $this->createSelectMock(null, false, false); $this->mockBuilders($select); $query = $this->getMockBuilder('Magento\\Framework\\Search\\Request\\QueryInterface')->setMethods(['getType'])->disableOriginalConstructor()->getMockForAbstractClass(); $query->expects($this->exactly(2))->method('getType')->will($this->returnValue('unknownQuery')); $this->connectionAdapter->expects($this->never())->method('select'); $this->connectionAdapter->expects($this->never())->method('dropTable'); $this->request->expects($this->once())->method('getQuery')->will($this->returnValue($query)); $this->mapper->buildQuery($this->request); }
public function testBuildWithoutOutOfStock() { $tableSuffix = '_table'; $index = 'test_index_name'; $this->request->expects($this->once())->method('getIndex')->will($this->returnValue($index)); $this->resource->expects($this->any())->method('getTableName')->will($this->returnCallback(function ($index) use($tableSuffix) { return $index . $tableSuffix; })); $this->select->expects($this->once())->method('from')->with(['search_index' => $index . $tableSuffix], ['entity_id' => 'search_index.product_id'])->will($this->returnSelf()); $this->select->expects($this->at(1))->method('joinLeft')->with(['category_index' => 'catalog_category_product_index' . $tableSuffix], 'search_index.product_id = category_index.product_id' . ' AND search_index.store_id = category_index.store_id', [])->will($this->returnSelf()); $this->config->expects($this->once())->method('isSetFlag')->with('cataloginventory/options/show_out_of_stock')->will($this->returnValue(false)); $this->adapter->expects($this->once())->method('quoteInto')->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1'); $website = $this->getMockBuilder('Magento\\Store\\Model\\Website')->disableOriginalConstructor()->getMock(); $website->expects($this->once())->method('getId')->willReturn(1); $this->storeManager->expects($this->once())->method('getWebsite')->willReturn($website); $this->select->expects($this->at(2))->method('joinLeft')->with(['stock_index' => 'cataloginventory_stock_status' . $tableSuffix], 'search_index.product_id = stock_index.product_id' . ' AND stock_index.website_id = 1', [])->will($this->returnSelf()); $this->select->expects($this->once())->method('where')->with('stock_index.stock_status = ?', 1)->will($this->returnSelf()); $result = $this->target->build($this->request); $this->assertSame($this->select, $result); }
/** * Test for method "build" */ public function testBuild() { $fetchResult = ['name' => ['some', 'result']]; $documents = [1 => 'document_1', 2 => 'document_2']; $this->aggregationResolver->expects($this->once())->method('resolve')->with($this->request, array_keys($documents))->willReturn([$this->bucket]); $this->bucket->expects($this->once())->method('getName')->willReturn('name'); $this->request->expects($this->once())->method('getDimensions')->willReturn([]); $this->bucketBuilder->expects($this->once())->method('build')->willReturn($fetchResult['name']); $result = $this->builder->build($this->request, $this->table, $documents); $this->assertEquals($fetchResult, $result); }
/** * Test for method "build" */ public function testBuild() { $fetchResult = ['name' => ['some', 'result']]; /** @var \Magento\Framework\DB\Ddl\Table|\PHPUnit_Framework_MockObject_MockObject $table */ $table = $this->getMockBuilder('Magento\\Framework\\DB\\Ddl\\Table')->disableOriginalConstructor()->getMock(); $this->bucket->expects($this->once())->method('getName')->willReturn('name'); $this->request->expects($this->once())->method('getAggregation')->willReturn([$this->bucket]); $this->request->expects($this->once())->method('getDimensions')->willReturn([]); $this->bucketBuilder->expects($this->once())->method('build')->willReturn($fetchResult['name']); $result = $this->builder->build($this->request, $table); $this->assertEquals($result, $fetchResult); }
public function testAddBoolFilterWithBoolFiltersInside() { $this->createAttributeMock('must1', null, null, 101, 'select', 0); $this->createAttributeMock('should1', null, null, 102, 'select', 1); $this->createAttributeMock('mustNot1', null, null, 103, 'select', 2); $query = $this->createFilterQuery($this->createBoolFilter([$this->createBoolFilter([$this->createTermFilter('must1')], [], [])], [$this->createBoolFilter([$this->createTermFilter('should1')], [], [])], [$this->createBoolFilter([$this->createTermFilter('mustNot1')], [], [])])); $this->request->expects($this->once())->method('getQuery')->willReturn($query); $this->select->expects($this->at(0))->method('joinLeft')->with(['must1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = must1_filter.entity_id' . ' AND must1_filter.attribute_id = 101' . ' AND must1_filter.store_id = 2514', [])->willReturnSelf(); $this->select->expects($this->at(1))->method('joinLeft')->with(['should1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = should1_filter.entity_id' . ' AND should1_filter.attribute_id = 102' . ' AND should1_filter.store_id = 2514', [])->willReturnSelf(); $this->select->expects($this->at(2))->method('joinLeft')->with(['mustNot1_filter' => 'prefix_catalog_product_index_eav'], 'search_index.entity_id = mustNot1_filter.entity_id' . ' AND mustNot1_filter.attribute_id = 103' . ' AND mustNot1_filter.store_id = 2514', [])->willReturnSelf(); $select = $this->target->addTables($this->select, $this->request); $this->assertEquals($this->select, $select, 'Returned results isn\'t equal to passed select'); }
public function testBuild() { $this->scoreBuilder->expects($this->once())->method('build')->willReturn('score condition'); $subSelect = $this->getMockBuilder('Magento\Framework\DB\Select') ->disableOriginalConstructor() ->getMock(); $this->indexBuilder->expects($this->once())->method('build')->willReturn($subSelect); $subSelect->expects($this->once())->method('columns')->with('score condition'); $this->request->expects($this->once())->method('getSize')->willReturn(1000); $subSelect->expects($this->once())->method('limit')->with(1000); $result = $this->queryContainer->addMatchQuery($this->select, $this->query, Bool::QUERY_CONDITION_MUST); $this->assertEquals($this->select, $result); }
protected function mockBuild($index, $tableSuffix, $hasFilters = false) { $this->request->expects($this->atLeastOnce())->method('getIndex')->will($this->returnValue($index)); $this->resource->expects($this->any())->method('getTableName')->will($this->returnCallback(function ($index) { return is_array($index) ? $index[0] . $index[1] : $index; })); $this->scopeResolver->expects($this->any())->method('resolve')->will($this->returnCallback(function ($index, $dimensions) { $tableNameParts = []; foreach ($dimensions as $dimension) { $tableNameParts[] = $dimension->getName() . $dimension->getValue(); } return $index . '_' . implode('_', $tableNameParts); })); $this->select->expects($this->at(0))->method('from')->with(['search_index' => $index . '_' . $tableSuffix], ['entity_id' => 'entity_id'])->will($this->returnSelf()); $this->select->expects($this->at(1))->method('joinLeft')->with(['cea' => 'catalog_eav_attribute'], 'search_index.attribute_id = cea.attribute_id', [])->will($this->returnSelf()); if ($hasFilters) { $this->select->expects($this->at(2))->method('joinLeft')->with(['category_index' => 'catalog_category_product_index'], 'search_index.entity_id = category_index.product_id', [])->will($this->returnSelf()); $this->select->expects($this->at(3))->method('joinLeft')->with(['cpie' => $this->resource->getTableName('catalog_product_index_eav')], 'search_index.entity_id = cpie.entity_id AND search_index.attribute_id = cpie.attribute_id', [])->willReturnSelf(); } }
/** * Add filtering by dimensions * * @param RequestInterface $request * @param Select $select * @return \Magento\Framework\DB\Select */ private function processDimensions(RequestInterface $request, Select $select) { $dimensions = []; foreach ($request->getDimensions() as $dimension) { $dimensions[] = $this->dimensionsBuilder->build($dimension); } $query = $this->conditionManager->combineQueries($dimensions, Select::SQL_OR); if (!empty($query)) { $select->where($this->conditionManager->wrapBrackets($query)); } return $select; }
/** * Add filtering by dimensions * * @param RequestInterface $request * @param Select $select * @return \Magento\Framework\DB\Select */ private function processDimensions(RequestInterface $request, Select $select) { $dimensions = []; foreach ($request->getDimensions() as $dimension) { $dimensions[] = $this->dimensionsBuilder->build($dimension); } if (!empty($dimensions)) { $query = sprintf('(%s)', implode(' ' . Select::SQL_OR . ' ', $dimensions)); $select->where($query); } 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; }
/** * {@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; }
/** * Add filtering by dimensions * * @param RequestInterface $request * @param Select $select * @return \Magento\Framework\DB\Select */ private function processDimensions(RequestInterface $request, Select $select) { $dimensions = $this->prepareDimensions($request->getDimensions()); $query = $this->conditionManager->combineQueries($dimensions, Select::SQL_OR); if (!empty($query)) { $select->where($this->conditionManager->wrapBrackets($query)); } 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 ); $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; }
/** * @param RequestInterface $request * @return bool */ private function isNeedToAddFilters(RequestInterface $request) { return $this->hasFilters($request->getQuery()); }
/** * 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; }