/** * @param \Elastica\Query $query * @param \Spryker\Client\Search\Dependency\Plugin\SortConfigBuilderInterface $sortConfig * @param array $requestParameters * * @return void */ protected function addSortingToQuery(Query $query, SortConfigBuilderInterface $sortConfig, array $requestParameters) { $sortParamName = $sortConfig->getActiveParamName($requestParameters); $sortConfigTransfer = $sortConfig->get($sortParamName); if ($sortConfigTransfer === null) { return; } $nestedSortField = $sortConfigTransfer->getFieldName() . '.' . $sortConfigTransfer->getName(); $query->setSort([$nestedSortField => ['order' => $sortConfig->getSortDirection($sortParamName), 'mode' => 'min']]); }
/** * @inheritdoc */ public function findPaginatedByQueryAndCategory(\string $queryString = null, \string $category = null, \int $priceFrom = null, \int $priceTo = null, \bool $availability = null) { $queryObject = new Query(); $filter = new BoolAnd(); if ($queryString) { $query = new Match('_all', ['query' => $queryString, 'operator' => 'AND']); } else { $query = new Query\MatchAll(); } if ($availability !== null) { $filter->addFilter(new Term(['availability' => $availability])); } $range = []; if ($priceFrom) { $range['gte'] = $priceFrom; } if ($priceTo) { $range['lte'] = $priceTo; } if ($range) { $filter->addFilter(new Range('price', $range)); } if ($category) { $term = new Term(['category.id' => $category]); $queryObject->setPostFilter($term); } $terms = new Terms('categories'); $terms->setField('category.id'); $terms->setSize(0); $queryObject->addAggregation($terms); if ($filter->getFilters()) { $filtered = new Query\Filtered($query, $filter); $queryObject->setQuery($filtered); } else { $queryObject->setQuery($query); } $queryObject->setSort(['updated' => 'desc']); $queryObject->setMinScore(0.5); return $this->findPaginated($queryObject); }
/** * @param string $term text to search * @return \Status */ public function searchText($term) { $term = trim($term); // No searching for nothing! That takes forever! if (!$term) { return null; } $query = new Query(); $offset = min($this->offset, static::MAX_OFFSET); if ($offset) { $query->setFrom($offset); } if ($this->limit) { $query->setSize($this->limit); } $filter = new Bool(); // filters if ($this->namespaces) { $filter->addMust(new Terms('namespace', $this->namespaces)); } if ($this->pageIds) { $filter->addMust(new Terms('pageid', $this->pageIds)); } if ($this->moderationStates) { $filter->addMust(new Terms('revisions.moderation_state', $this->moderationStates)); } // only apply filters if there are any if ($filter->toArray()) { $query->setFilter($filter); } $sortArgs = $this->getSortArgs(); if (isset($sortArgs[$this->sort]) && $sortArgs[$this->sort]) { $query->setSort($sortArgs[$this->sort]); } // @todo: interwiki stuff? (see \CirrusSearch) $searcher = new Searcher($query, false, $this->type); return $searcher->searchText($term); }
/** * Powers full-text-like searches including prefix search. * * @param string $type * @param string $for * @return Status(mixed) results from the query transformed by the resultsType */ private function search($type, $for) { if ($this->nonTextQueries) { $bool = new \Elastica\Query\Bool(); if ($this->query !== null) { $bool->addMust($this->query); } foreach ($this->nonTextQueries as $nonTextQuery) { $bool->addMust($nonTextQuery); } $this->query = $bool; } if ($this->resultsType === null) { $this->resultsType = new FullTextResultsType(FullTextResultsType::HIGHLIGHT_ALL); } // Default null queries now so the rest of the method can assume it is not null. if ($this->query === null) { $this->query = new \Elastica\Query\MatchAll(); } $query = new Elastica\Query(); $query->setParam('_source', $this->resultsType->getSourceFiltering()); $query->setParam('fields', $this->resultsType->getFields()); $extraIndexes = array(); $indexType = $this->pickIndexTypeFromNamespaces(); if ($this->namespaces) { $extraIndexes = $this->getAndFilterExtraIndexes(); if ($this->needNsFilter($extraIndexes, $indexType)) { $this->filters[] = new \Elastica\Filter\Terms('namespace', $this->namespaces); } } // Wrap $this->query in a filtered query if there are any filters $unifiedFilter = Filters::unify($this->filters, $this->notFilters); if ($unifiedFilter !== null) { $this->query = new \Elastica\Query\Filtered($this->query, $unifiedFilter); } // Call installBoosts right after we're done munging the query to include filters // so any rescores installBoosts adds to the query are done against filtered results. $this->installBoosts(); $query->setQuery($this->query); $highlight = $this->resultsType->getHighlightingConfiguration($this->highlightSource); if ($highlight) { // Fuzzy queries work _terribly_ with the plain highlighter so just drop any field that is forcing // the plain highlighter all together. Do this here because this works so badly that no // ResultsType should be able to use the plain highlighter for these queries. if ($this->fuzzyQuery) { $highlight['fields'] = array_filter($highlight['fields'], function ($field) { return $field['type'] !== 'plain'; }); } if (!empty($this->nonTextHighlightQueries)) { // We have some phrase_prefix queries, so let's include them in the // generated highlight_query. $bool = new \Elastica\Query\Bool(); if ($this->highlightQuery) { $bool->addShould($this->highlightQuery); } foreach ($this->nonTextHighlightQueries as $nonTextHighlightQuery) { $bool->addShould($nonTextHighlightQuery); } $this->highlightQuery = $bool; } if ($this->highlightQuery) { $highlight['highlight_query'] = $this->highlightQuery->toArray(); } $query->setHighlight($highlight); } if ($this->suggest) { $query->setParam('suggest', $this->suggest); $query->addParam('stats', 'suggest'); } if ($this->offset) { $query->setFrom($this->offset); } if ($this->limit) { $query->setSize($this->limit); } if ($this->sort != 'relevance') { // Clear rescores if we aren't using relevance as the search sort because they aren't used. $this->rescore = array(); } if ($this->rescore) { // rescore_query has to be in array form before we send it to Elasticsearch but it is way easier to work // with if we leave it in query for until now $modifiedRescore = array(); foreach ($this->rescore as $rescore) { $rescore['query']['rescore_query'] = $rescore['query']['rescore_query']->toArray(); $modifiedRescore[] = $rescore; } $query->setParam('rescore', $modifiedRescore); } $query->addParam('stats', $type); switch ($this->sort) { case 'relevance': break; // The default // The default case 'title_asc': $query->setSort(array('title.keyword' => 'asc')); break; case 'title_desc': $query->setSort(array('title.keyword' => 'desc')); break; case 'incoming_links_asc': $query->setSort(array('incoming_links' => array('order' => 'asc', 'missing' => '_first'))); break; case 'incoming_links_desc': $query->setSort(array('incoming_links' => array('order' => 'desc', 'missing' => '_last'))); break; default: LoggerFactory::getInstance('CirrusSearch')->warning("Invalid sort type: {sort}", array('sort' => $this->sort)); } $queryOptions = array(); if ($this->config->get('CirrusSearchMoreAccurateScoringMode')) { $queryOptions['search_type'] = 'dfs_query_then_fetch'; } switch ($type) { case 'regex': $poolCounterType = 'CirrusSearch-Regex'; $queryOptions['timeout'] = $this->config->getElement('CirrusSearchSearchShardTimeout', 'regex'); break; case 'prefix': $poolCounterType = 'CirrusSearch-Prefix'; $queryOptions['timeout'] = $this->config->getElement('CirrusSearchSearchShardTimeout', 'default'); break; default: $poolCounterType = 'CirrusSearch-Search'; $queryOptions['timeout'] = $this->config->getElement('CirrusSearchSearchShardTimeout', 'default'); } $this->connection->setTimeout($queryOptions['timeout']); // Setup the search $pageType = $this->connection->getPageType($this->indexBaseName, $indexType); $search = $pageType->createSearch($query, $queryOptions); foreach ($extraIndexes as $i) { $search->addIndex($i); } $description = "{queryType} search for '{query}'"; $logContext = array('queryType' => $type, 'query' => $for); if ($this->returnQuery) { return Status::newGood(array('description' => $this->formatDescription($description, $logContext), 'path' => $search->getPath(), 'params' => $search->getOptions(), 'query' => $query->toArray(), 'options' => $queryOptions)); } if ($this->returnExplain && $this->returnResult) { $query->setExplain(true); } // Perform the search $searcher = $this; $user = $this->user; $result = Util::doPoolCounterWork($poolCounterType, $this->user, function () use($searcher, $search, $description, $logContext) { try { $searcher->start($description, $logContext); return $searcher->success($search->search()); } catch (\Elastica\Exception\ExceptionInterface $e) { return $searcher->failure($e); } }, function ($error, $key, $userName) use($type, $description, $user, $logContext) { $forUserName = $userName ? "for {userName} " : ''; LoggerFactory::getInstance('CirrusSearch')->warning("Pool error {$forUserName}on key {key} during {$description}: {error}", $logContext + array('userName' => $userName, 'key' => 'key', 'error' => $error)); if ($error === 'pool-queuefull') { if (strpos($key, 'nowait:CirrusSearch:_per_user') === 0) { $loggedIn = $user->isLoggedIn() ? 'logged-in' : 'anonymous'; return Status::newFatal("cirrussearch-too-busy-for-you-{$loggedIn}-error"); } if ($type === 'regex') { return Status::newFatal('cirrussearch-regex-too-busy-error'); } return Status::newFatal('cirrussearch-too-busy-error'); } return Status::newFatal('cirrussearch-backend-error'); }); if ($result->isOK()) { $responseData = $result->getValue()->getResponse()->getData(); if ($this->returnResult) { return Status::newGood(array('description' => $this->formatDescription($description, $logContext), 'path' => $search->getPath(), 'result' => $responseData)); } $result->setResult(true, $this->resultsType->transformElasticsearchResult($this->suggestPrefixes, $this->suggestSuffixes, $result->getValue(), $this->searchContext->isSearchContainedSyntax())); if (isset($responseData['timed_out']) && $responseData['timed_out']) { LoggerFactory::getInstance('CirrusSearch')->warning("{$description} timed out and only returned partial results!", $logContext); if ($result->getValue()->numRows() === 0) { return Status::newFatal('cirrussearch-backend-error'); } else { $result->warning('cirrussearch-timed-out'); } } } return $result; }
/** * Search children. * * @param string $type Post type * @param int $parent Parent ID to get all children * @param string $order Order way * @return array $search Combine of all results, total and aggregations * * @since 3.0.0 */ public function searchChildren($type, $parent, $order = 'desc') { //Check page if (is_search()) { return; } //Return array $return = array('parent' => $parent, 'total' => 0, 'results' => array()); //Check request if (empty($parent)) { return $return; } //Get query vars $results = array(); $types = array(); //Get Elasticsearch datas $index = $this->getIndex(); //Check index if (null === $index || empty($index)) { return $return; } //Create the actual search object with some data. $es_query = new Query(); //Define term $es_term = new Term(); $es_term->setTerm($type . '.parent', $parent); //Filter 'And' $es_filter = new Bool(); $es_filter->addMust($es_term); //Add filter to the search object $es_query->setFilter($es_filter); //Add sort $es_query->setSort(array($type . '.date' => array('order' => $order))); //Search! $es_resultset = $index->search($es_query); //Retrieve data $es_results = $es_resultset->getResults(); //Check results if (null == $es_results || empty($es_results)) { return $return; } //Iterate to retrieve all IDs foreach ($es_results as $res) { $typ = $res->getType(); //Save type $types[$typ] = $typ; //Save datas $results[$typ][] = array('id' => $res->getId(), 'score' => $res->getScore(), 'source' => $res->getSource()); } //Get total $total = $es_resultset->getTotalHits(); //Return everything $return = array('parent' => $parent, 'total' => $total, 'results' => $results); return $return; }
/** * @param string $term * @param string $value * @param int $size * * @return \Elastica\ResultSet */ public function termQuery($term, $value, $size = 30) { $_agg = new Aggregation(); $_facet = $_agg->date_histogram('occurred_on', '@timestamp', ElkIntervals::DAY); // $_facet = new DateHistogram('occurred_on'); // $_facet->setField('@timestamp'); // $_facet->setInterval('day'); $_query = new Query(); $_query->setSize($size); $_query->setSort(['@timestamp']); // Filter for term $_filter = new Prefix($term, $value); $_and = new Bool(); $_and->addMust($_filter); $_query->setPostFilter($_and); $_query->addAggregation($_facet); $_results = $this->_doSearch($_query); return $_results; }
/** * {@inheritdoc} */ public function generateQueryBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) { $query = new Query(); if (empty($criteria)) { $query->setQuery(new MatchAll()); } else { $query->setQuery(new Filtered(null, $this->generateFilterBy($criteria))); } if ($orderBy) { $query->setSort($orderBy); } if ($limit) { $query->setSize($limit); } if ($offset) { $query->setFrom($offset); } return $query; }
public function publisherAction(Request $request, $page = 1) { $getTypes = $request->query->get('type_filters'); $typeFilters = !empty($getTypes) ? explode(',', $getTypes) : []; $publisherSearcher = $this->get('fos_elastica.index.search.publisher'); $boolQuery = new Query\BoolQuery(); if (!empty($typeFilters)) { foreach ($typeFilters as $type) { $match = new Query\Match(); $match->setField('publisherType', $type); $boolQuery->addMust($match); } } $publisherQuery = new Query($boolQuery); $publisherQuery->setSort(['name.raw' => ['order' => 'asc']]); $typeAgg = new Aggregation\Terms('types'); $typeAgg->setField('publisher.publisherType.name'); $typeAgg->setOrder('_term', 'asc'); $typeAgg->setSize(0); $publisherQuery->addAggregation($typeAgg); $adapter = new ElasticaAdapter($publisherSearcher, $publisherQuery); $pagerfanta = new Pagerfanta($adapter); $pagerfanta->setMaxPerPage(20); $pagerfanta->setCurrentPage($page); $publishers = $pagerfanta->getCurrentPageResults(); $types = $adapter->getResultSet()->getAggregation('types')['buckets']; $data = ['types' => $types, 'page' => 'ojs_site_explore_publisher', 'publishers' => $publishers, 'pagerfanta' => $pagerfanta, 'type_filters' => $typeFilters]; return $this->render('OjsSiteBundle:Explore:publisher.html.twig', $data); }
public function sortBy($sort) { $query = new \Elastica\Query('agg_name'); $query->setSort($sort); $this->query[] = $query; return $query; }