/** * Rewrite the query. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * * @param QueryBuilder $subject Original query builder. * @param \Closure $proceed Original create func. * @param ContainerConfigurationInterface $containerConfig Search request container config. * @param string $queryText Current query text. * @param string $spellingType Spelling type of the query. * @param float $boost Original query boost. * * @return QueryInterface */ public function aroundCreate(QueryBuilder $subject, \Closure $proceed, ContainerConfigurationInterface $containerConfig, $queryText, $spellingType, $boost = 1) { $storeId = $containerConfig->getStoreId(); $requestName = $containerConfig->getName(); $rewriteCacheKey = $requestName . '|' . $storeId . '|' . md5(json_encode($queryText)); if (!isset($this->rewritesCache[$rewriteCacheKey])) { $query = $proceed($containerConfig, $queryText, $spellingType, $boost); $rewrites = []; if (!is_array($queryText)) { $queryText = [$queryText]; } foreach ($queryText as $currentQueryText) { $rewrites = array_merge($rewrites, $this->index->getQueryRewrites($containerConfig, $currentQueryText)); } if (!empty($rewrites)) { $synonymQueries = [$query]; $synonymQueriesSpellcheck = SpellcheckerInterface::SPELLING_TYPE_EXACT; foreach ($rewrites as $rewrittenQuery => $weight) { $synonymQueries[] = $proceed($containerConfig, $rewrittenQuery, $synonymQueriesSpellcheck, $weight); } $query = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['should' => $synonymQueries]); } $this->rewritesCache[$rewriteCacheKey] = $query; } return $this->rewritesCache[$rewriteCacheKey]; }
/** * Prepare filter condition from an array as used into addFieldToFilter. * * @SuppressWarnings(PHPMD.ElseExpression) * * @param ContainerConfigurationInterface $containerConfig Search request container configuration. * @param array $filters Filters to be built. * * @return QueryInterface */ public function create(ContainerConfigurationInterface $containerConfig, array $filters) { $queries = []; $mapping = $containerConfig->getMapping(); foreach ($filters as $fieldName => $condition) { if ($condition instanceof QueryInterface) { $queries[] = $condition; } else { $mappingField = $mapping->getField($fieldName); $queries[] = $this->prepareFieldCondition($mappingField, $condition); } } $filterQuery = current($queries); if (count($queries) > 1) { $filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries]); } return $filterQuery; }
/** * Build the list of buckets from the mapping. * * @param ContainerConfigurationInterface $containerConfiguration Search request configuration * @param array $aggregations Facet definitions. * @param array $filters Facet filters to be added to buckets. * * @return BucketInterface[] */ public function buildAggregations(ContainerConfigurationInterface $containerConfiguration, array $aggregations, array $filters) { $buckets = []; $mapping = $containerConfiguration->getMapping(); foreach ($aggregations as $fieldName => $aggregationParams) { $bucketType = $aggregationParams['type']; try { $field = $mapping->getField($fieldName); $bucketParams = $this->getBucketParams($field, $aggregationParams, $filters); if (isset($bucketParams['filter'])) { $bucketParams['filter'] = $this->createFilter($containerConfiguration, $bucketParams['filter']); } if (isset($bucketParams['nestedFilter'])) { $nestedFilter = $this->createFilter($containerConfiguration, $bucketParams['nestedFilter']); $bucketParams['nestedFilter'] = $nestedFilter->getQuery(); } } catch (\Exception $e) { $bucketParams = $aggregationParams['config']; } $buckets[] = $this->aggregationFactory->create($bucketType, $bucketParams); } return $buckets; }
/** * Build sort orders from array of sort orders definition. * * @param ContainerConfigurationInterface $containerConfig Request configuration. * @param array $orders Sort orders definitions. * * @return SortOrderInterface[] */ public function buildSordOrders(ContainerConfigurationInterface $containerConfig, array $orders) { $sortOrders = []; $mapping = $containerConfig->getMapping(); $orders = $this->addDefaultSortOrders($orders, $mapping); foreach ($orders as $fieldName => $sortOrderParams) { $factory = $this->standardOrderFactory; try { $sortField = $mapping->getField($fieldName); $sortOrderParams = $this->getSortOrderParams($sortField, $sortOrderParams); if (isset($sortOrderParams['nestedPath'])) { $factory = $this->nestedOrderFactory; } if (isset($sortOrderParams['nestedFilter'])) { $nestedFilter = $this->queryBuilder->create($containerConfig, $sortOrderParams['nestedFilter']); $sortOrderParams['nestedFilter'] = $nestedFilter->getQuery(); } } catch (\LogicException $e) { $sortOrderParams['field'] = $fieldName; } $sortOrders[] = $factory->create($sortOrderParams); } return $sortOrders; }
/** * Build an array of weighted fields to be searched with the ability to apply a filter callback method and a default field. * * @param ContainerConfigurationInterface $containerConfig Search request container config. * @param string $analyzer Target analyzer. * @param callable $filterCallback Field filter callback. * @param string|null $defaultField Default search field. * @param integer $boost Additional boost applied to the fields (multiplicative). * * @return array */ private function getWeightedFields(ContainerConfigurationInterface $containerConfig, $analyzer = FieldInterface::ANALYZER_STANDARD, $filterCallback = null, $defaultField = null, $boost = 1) { $weightedFields = []; if ($defaultField !== null) { if ($analyzer != FieldInterface::ANALYZER_STANDARD) { $defaultField = sprintf("%s.%s", $defaultField, $analyzer); } $weightedFields[$defaultField] = 1; } $fields = $containerConfig->getMapping()->getFields(); if ($filterCallback) { $fields = array_filter($fields, $filterCallback); } foreach ($fields as $field) { $mappingProperty = $field->getMappingProperty($analyzer); if ($mappingProperty && ($defaultField === null || $field->getSearchWeight() != 1)) { $weightedFields[$mappingProperty] = $field->getSearchWeight() * $boost; } } return $weightedFields; }
/** * Load the thesaurus config for the current container. * * @param ContainerConfigurationInterface $containerConfig Search request container config. * * @return ThesaurusConfig */ private function getConfig(ContainerConfigurationInterface $containerConfig) { $storeId = $containerConfig->getStoreId(); $containerName = $containerConfig->getName(); return $this->thesaurusConfigFactory->create($storeId, $containerName); }