public function findWithTenant($searchText, $tenantId, $sortDirection = 'desc') { $boolFilter = new Filter\Bool(); $boolFilter->addMust(new Filter\Term(['tenant.id' => $tenantId])); $boolQuery = new Query\Bool(); if ($searchText !== null) { $fieldQuery = new Query\MultiMatch(); $fieldQuery->setQuery("*" . $searchText . "*"); $fieldQuery->setFields(['name', 'description']); $boolQuery->addMust($fieldQuery); } $filtered = new Query\Filtered($boolQuery, $boolFilter); $query = Query::create($filtered); $query->addSort(['created_at' => $sortDirection]); return $this->findPaginated($query); }
/** * search page index controller * * @param Request $request * @param int $page * @return \Symfony\Component\HttpFoundation\Response */ public function indexAction(Request $request, $page = 1) { /** * @var \Ojs\SearchBundle\Manager\SearchManager $searchManager */ $searchManager = $this->get('ojs_search_manager'); $getRoles = $request->query->get('role_filters'); $getSubjects = $request->query->get('subject_filters'); $getJournals = $request->query->get('journal_filters'); $roleFilters = !empty($getRoles) ? explode(',', $getRoles) : []; $subjectFilters = !empty($getSubjects) ? explode(',', $getSubjects) : []; $journalFilters = !empty($getJournals) ? explode(',', $getJournals) : []; $queryType = $request->query->has('type') ? $request->get('type') : 'basic'; $query = filter_var($request->get('q'), FILTER_SANITIZE_STRING); $section = filter_var($request->get('section'), FILTER_SANITIZE_STRING); $searcher = $this->get('fos_elastica.index.search'); $searchQuery = new Query('_all'); $boolQuery = new Query\Bool(); $match = new Query\Match(); $match->setField('status', 3); $boolQuery->addShould($match); $match = new Query\Match(); $match->setField('published', true); $boolQuery->addShould($match); //set query according to query type if ($queryType == 'basic') { $fieldQuery = new Query\MultiMatch(); $fieldQuery->setFields(['_all']); $fieldQuery->setQuery($query); $boolQuery->addMust($fieldQuery); } elseif ($queryType == 'advanced') { $parseQuery = $searchManager->parseSearchQuery($query); foreach ($parseQuery as $searchTerm) { $condition = $searchTerm['condition']; $advancedFieldQuery = new Query\MultiMatch(); $advancedFieldQuery->setFields([$searchTerm['searchField']]); $advancedFieldQuery->setQuery($searchTerm['searchText']); if ($condition == 'AND') { $boolQuery->addMust($advancedFieldQuery); } elseif ($condition == 'OR') { $boolQuery->addShould($advancedFieldQuery); } elseif ($condition == 'NOT') { $boolQuery->addMustNot($advancedFieldQuery); } } } elseif ($queryType == 'tag') { $matchQuery = new Query\Match(); $matchQuery->setField('tags', $query); $boolQuery->addMust($matchQuery); } //set aggregations if requested if (!empty($roleFilters) || !empty($subjectFilters) || !empty($journalFilters)) { foreach ($roleFilters as $role) { $match = new Query\Match(); $match->setField('user.userJournalRoles.role.name', $role); $boolQuery->addMust($match); } foreach ($subjectFilters as $subject) { $match = new Query\Match(); $match->setField('subjects', $subject); $boolQuery->addMust($match); } foreach ($journalFilters as $journal) { $match = new Query\Match(); $match->setField('user.userJournalRoles.journal.title', $journal); $boolQuery->addMust($match); } } //set our boolean query $searchQuery->setQuery($boolQuery); //get all result $searchQuery->setSize(1000); //get role aggregation $roleAgg = new Aggregation\Terms('roles'); $roleAgg->setField('userJournalRoles.role.name'); $roleAgg->setOrder('_term', 'asc'); $roleAgg->setSize(0); $searchQuery->addAggregation($roleAgg); //get subject aggregation $subjectAgg = new Aggregation\Terms('subjects'); $subjectAgg->setField('subjects'); $subjectAgg->setOrder('_term', 'asc'); $subjectAgg->setSize(0); $searchQuery->addAggregation($subjectAgg); //get journal aggregation $journalAgg = new Aggregation\Terms('journals'); $journalAgg->setField('journal.raw'); $journalAgg->setOrder('_term', 'asc'); $journalAgg->setSize(0); $searchQuery->addAggregation($journalAgg); /** * @var ResultSet $resultData */ $resultData = $searcher->search($searchQuery); $roles = $resultData->getAggregation('roles')['buckets']; $subjects = $resultData->getAggregation('subjects')['buckets']; $journals = $resultData->getAggregation('journals')['buckets']; if ($resultData->count() > 0) { /** * manipulate result data for easily use on template */ $results = $searchManager->buildResultsObject($resultData, $section); /** * if search section is not defined or empty redirect to first result section */ if (empty($section)) { $section = array_keys($results)[0]; $redirectParams = array_merge($request->query->all(), ['section' => $section]); return $this->redirectToRoute('ojs_search_index', $redirectParams); } else { /** * if section result is empty redirect to first that have result section */ if (!isset($results[$section])) { foreach ($results as $resultKey => $result) { if ($result['total_item'] > 0) { $redirectParams = array_merge($request->query->all(), ['section' => $resultKey]); return $this->redirectToRoute('ojs_search_index', $redirectParams); } } } } $adapter = new ArrayAdapter($results[$section]['data']); $pagerfanta = new Pagerfanta($adapter); $pagerfanta->setMaxPerPage(10); $pagerfanta->setCurrentPage($page); $results[$section]['data'] = $pagerfanta->getCurrentPageResults(); /** * add search query to query history * history data stores on session */ $this->addQueryToHistory($request, $query, $queryType, $resultData->count()); $data = ['results' => $results, 'query' => $query, 'queryType' => $queryType, 'section' => $section, 'total_count' => $searchManager->getTotalHit(), 'roles' => $roles, 'subjects' => $subjects, 'journals' => $journals, 'role_filters' => $roleFilters, 'subject_filters' => $subjectFilters, 'journal_filters' => $journalFilters, 'pagerfanta' => $pagerfanta]; } else { $data = ['query' => $query, 'queryType' => $queryType, 'total_count' => $searchManager->getTotalHit(), 'journals' => []]; } return $this->render('OjsSiteBundle:Search:index.html.twig', $data); }
public function testQuery() { $client = $this->_getClient(); $index = new Index($client, 'test'); $index->create(array(), true); $type = new Type($index, 'multi_match'); $doc = new Document(1, array('id' => 1, 'name' => 'Rodolfo', 'last_name' => 'Moraes')); $type->addDocument($doc); // Refresh index $index->refresh(); $multiMatch = new MultiMatch(); $query = new Query(); $multiMatch->setQuery('Rodolfo'); $multiMatch->setFields(array('name', 'last_name')); $query->setQuery($multiMatch); $resultSet = $index->search($query); $this->assertEquals(1, $resultSet->count()); $multiMatch->setQuery('Moraes'); $multiMatch->setFields(array('name', 'last_name')); $query->setQuery($multiMatch); $resultSet = $index->search($query); $this->assertEquals(1, $resultSet->count()); }
/** * @param string[] $fields * @param string[] $nearMatchFields * @param string $queryString * @param string $nearMatchQuery * @return \Elastica\Query\Simple|\Elastica\Query\Bool */ private function buildSearchTextQuery(array $fields, array $nearMatchFields, $queryString, $nearMatchQuery) { $queryForMostFields = $this->buildSearchTextQueryForFields($fields, $queryString, $this->config->getElement('CirrusSearchPhraseSlop', 'default'), false); if ($nearMatchQuery) { // Build one query for the full text fields and one for the near match fields so that // the near match can run unescaped. $bool = new \Elastica\Query\Bool(); $bool->setMinimumNumberShouldMatch(1); $bool->addShould($queryForMostFields); $nearMatch = new \Elastica\Query\MultiMatch(); $nearMatch->setFields($nearMatchFields); $nearMatch->setQuery($nearMatchQuery); $bool->addShould($nearMatch); return $bool; } return $queryForMostFields; }
/** * Find all documents where the value is matched in the fields. The type option * allows you to specify the type of match, can be best_fields, most_fields, * cross_fields, phrase, phrase_prefix. * * best_fields finds documents which match any field, but uses the _score * from the best field. * * most_fields finds documents which match any field and combines the _score * from each field. * * cross_fields treats fields with the same analyzer as though they were * one big field. Looks for each word in any field. * * phrase runs a match_phrase query on each field and combines the _score * from each field. * * phrase_prefix runs a match_phrase_prefix query on each field and combines * the _score from each field. * * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html * * @param array $fields The fields to search in * @param string $query The string to search for * @param string $type The match type * @param bool $fuzzy Set whether the match should be fuzzy * @param float $tieBreaker Can be between 0.0 and 1.0 * @param string $operator Can be 'and' or 'or' * @return Query */ public function multiMatch(array $fields, $query, $type = 'phrase', $fuzzy = false, $tieBreaker = 0.0, $operator = 'and') { $match = new MultiMatch(); $match->setFields($fields); $match->setQuery($query); $match->setType($type); if ($fuzzy) { $match->setFuzziness('AUTO'); } if ($type == 'best_fields') { $match->setTieBreaker($tieBreaker); } if ($type == 'cross_fields') { $match->setOperator($operator); } $query = $this->newQuery($match); $this->query[] = $query; return $query; }
/** * @group functional */ public function testBaseMultiMatch() { $multiMatch = new MultiMatch(); $multiMatch->setQuery('Rodolfo'); $multiMatch->setFields(array('name', 'last_name')); $resultSet = $this->_getResults($multiMatch); $this->assertEquals(1, $resultSet->count()); $multiMatch = new MultiMatch(); $multiMatch->setQuery('Moraes'); $multiMatch->setFields(array('name', 'last_name')); $resultSet = $this->_getResults($multiMatch); $this->assertEquals(1, $resultSet->count()); }
public function search() { //$finder = $this->container->get('fos_elastica.finder.search.articles'); $bool = new Query\Bool(); $multiMatch = new Query\MultiMatch(); $multiMatch->setFields(['subjects', 'title', 'keywords', 'subtitle', 'citations.raw', 'journal.title', 'journal.subtitle']); $multiMatch->setType('phrase_prefix'); $multiMatch->setQuery($this->getParam('term')); $bool->addMust($multiMatch); if ($this->filter) { foreach ($this->filter as $key => $filter) { $filterObj = new Query\Match(); $this->applyFilter($filterObj, $key, $filter); $bool->addMust($filterObj); } } $missing = new Filter\Missing("issue"); $not = new Filter\BoolNot($missing); $notQ = new Query\Filtered(); $notQ->setFilter($not); $bool->addMust($notQ); $query = new Query(); $query->setQuery($bool); $query->setFrom($this->getPage() * $this->getLimit()); $query->setSize($this->getLimit()); $aggregation = new Terms('journals'); $aggregation->setField('journal.id'); $aggregation->setOrder('_count', 'desc'); $qb = $this->em->createQueryBuilder(); $qb->select('count(r.id)')->from('OjsJournalBundle:Journal', 'r')->where($qb->expr()->eq('r.status', 3)); $aggregation->setSize($qb->getQuery()->getSingleScalarResult()); $query->addAggregation($aggregation); $aggregation = new Terms('authors'); $aggregation->setField('articleAuthors.author.id'); $aggregation->setOrder('_count', 'desc'); $qb = $this->em->createQueryBuilder(); $qb->select('count(r.id)')->from('OjsJournalBundle:Author', 'r'); $aggregation->setSize($qb->getQuery()->getSingleScalarResult()); $query->addAggregation($aggregation); $elasticaAdapter = new ElasticaAdapter($this->index, $query); $pagerFanta = new Pagerfanta($elasticaAdapter); $pagerFanta->setMaxPerPage($this->getLimit()); $pagerFanta->setCurrentPage($this->getPage()); /** @var ResultSet $search */ $search = $pagerFanta->getCurrentPageResults(); $result = $search->getResults(); //$search->getResults(); $this->pager = $pagerFanta; $transformer = new ElasticaToModelTransformer($this->registry, 'OjsJournalBundle:Article'); $transformer->setPropertyAccessor($this->propertyAccessor); $this->result = $transformer->transform($result); $this->setCount($pagerFanta->getNbResults()); $this->addAggregation('journal', $this->transform($search->getAggregation('journals')['buckets'], 'OjsJournalBundle:Journal')); $this->addAggregation('author', $this->transform($search->getAggregation('authors')['buckets'], 'OjsJournalBundle:Author')); return $this; }
/** * @param Request $request * @return JsonResponse */ public function autoCompleteAction(Request $request) { $q = filter_var($request->get('q'), FILTER_SANITIZE_STRING); $search = $this->get('fos_elastica.index.search.journal'); $notCollectJournals = []; if ($request->query->has('notCollectJournals')) { $notCollectJournalsParam = $request->query->get('notCollectJournals'); if (!empty($notCollectJournalsParam) && is_array($notCollectJournalsParam)) { $notCollectJournals = $notCollectJournalsParam; } } $searchQuery = new Query('_all'); $boolQuery = new Query\BoolQuery(); $fieldQuery = new Query\MultiMatch(); $fieldQuery->setFields(['title']); $fieldQuery->setQuery(strtoupper($q)); $fieldQuery->setFuzziness(0.7); $boolQuery->addMust($fieldQuery); $searchQuery->setQuery($boolQuery); $searchQuery->setSize(10); $results = $search->search($searchQuery); $data = []; foreach ($results as $result) { if (!in_array($result->getId(), $notCollectJournals)) { $data[] = ['id' => $result->getId(), 'text' => $result->getData()['title']]; } } return new JsonResponse($data); }