public function searchDataset($criteria, $sorts = array(), $offset = 0, $limit = 0, $operator = 'OR') { if ($limit <= 0) { $limit = Yii::app()->params['es_search']['limits']['default']; } $keyword = $criteria['keyword']; $eQueryString = new \Elastica\Query\QueryString(); $eQueryString->setDefaultOperator($operator); $eQueryString->setQuery($keyword); $eQuery = new \Elastica\Query(); $eQuery->setQuery($eQueryString); $eQuery->setFrom($offset); $eQuery->setLimit($limit); $filterAnd = new \Elastica\Filter\BoolAnd(); if (isset($criteria['dataset_type'])) { $filterAnd->addFilter($this->newTerms('typenames', $criteria['dataset_type'])); } if (isset($criteria['project'])) { $filterAnd->addFilter($this->newTerms('projects', $criteria['project'])); } if (isset($criteria['external_link_type'])) { $filterAnd->addFilter($this->newTerms('link_types', $criteria['external_link_type'])); } if (isset($criteria['pubdate_from']) && isset($criteria['pubdate_to'])) { $pubfilter = new \Elastica\Filter\Range(); $pubfilter->addField('publication_date', array('from' => $criteria['pubdate_from'], 'to' => $criteria['pubdate_to'])); $filterAnd->addFilter($pubfilter); } elseif (isset($criteria['pubdate_from'])) { $pubfilter = new \Elastica\Filter\Range(); $pubfilter->addField('publication_date', array('from' => $criteria['pubdate_from'])); $filterAnd->addFilter($pubfilter); } elseif (isset($criteria['pubdate_to'])) { $pubfilter = new \Elastica\Filter\Range(); $pubfilter->addField('publication_date', array('to' => $criteria['pubdate_to'])); $filterAnd->addFilter($pubfilter); } $arrayAnd = $filterAnd; $arrayAnd = $arrayAnd->toArray(); if (count($arrayAnd['and']) > 0) { $eQuery->setPostFilter($filterAnd); } $sortList = array_merge(array('_score' => array('order' => 'desc')), $sorts); $eQuery->setSort($sortList); $index = Yii::app()->elastic->client->getIndex('gigadb'); $type = $index->getType('dataset'); $eResultSet = $type->search($eQuery); $results = $eResultSet->getResults(); $total = $eResultSet->getTotalHits(); $data = array(); foreach ($results as $result) { if ($result) { $data[] = $result->getData(); } } $re = array('data' => $data, 'total' => $total); //Yii::log(print_r($eResultSet, true), 'debug'); return $re; }
/** * To respect the design, 3 searches will be executed: * 1st: retrieves the main facet (Text / Media / Portfolio / Users / Group) and the count for each of them * 2nd: - retrieves the results of the first non empty facet term for display in the tab * - retrieves the secondary facet to enable / disable the filter items * 3nd: - retrieves the results with all filters applied * @param unknown $query_string * @param unknown $limit * @param unknown $offset * @param unknown $options * @param unknown $mainfacetterm * @param unknown $USER * @return multitype:number boolean unknown Ambigous <boolean, NULL> Ambigous <boolean, unknown> multitype:multitype:string number Ambigous <string, unknown> |multitype:multitype: */ public static function search($query_string, $limit, $offset, $options, $mainfacetterm, $USER) { $result = array('count' => 0, 'limit' => $limit, 'offset' => $offset, 'data' => false, 'selected' => isset($mainfacetterm) && strlen($mainfacetterm) > 0 ? $mainfacetterm : false, 'totalresults' => 0, 'facets' => array(array('term' => "Text", 'count' => 0, 'display' => "Text"), array('term' => "Media", 'count' => 0, 'display' => "Media"), array('term' => "Portfolio", 'count' => 0, 'display' => "Portfolio"), array('term' => "User", 'count' => 0, 'display' => "Users"), array('term' => "Group", 'count' => 0, 'display' => "Group")), 'content-filter' => array(array('term' => "all", 'count' => 0, 'display' => "All"), array('term' => "Audio", 'count' => 0, 'display' => "Audio"), array('term' => "Comment", 'count' => 0, 'display' => "Comment"), array('term' => "Document", 'count' => 0, 'display' => "Document"), array('term' => "Folder", 'count' => 0, 'display' => "Folder"), array('term' => "Forum", 'count' => 0, 'display' => "Forum"), array('term' => "Forumpost", 'count' => 0, 'display' => "Forum post"), array('term' => "Image", 'count' => 0, 'display' => "Image"), array('term' => "Journal", 'count' => 0, 'display' => "Journal"), array('term' => "Journalentry", 'count' => 0, 'display' => "Journal entry"), array('term' => "Note", 'count' => 0, 'display' => "Note"), array('term' => "Plan", 'count' => 0, 'display' => "Plan"), array('term' => "Profile", 'count' => 0, 'display' => "Profile"), array('term' => "Resume", 'count' => 0, 'display' => "Résumé"), array('term' => "Video", 'count' => 0, 'display' => "Video"), array('term' => "Wallpost", 'count' => 0, 'display' => "Wall post"), array('term' => "Collection", 'count' => 0, 'display' => "Collection"), array('term' => "Page", 'count' => 0, 'display' => "Page")), 'content-filter-selected' => isset($options['secfacetterm']) && strlen($options['secfacetterm']) > 0 ? $options['secfacetterm'] : 'all', 'owner-filter' => array(array('term' => "all", 'count' => 0, 'display' => "All"), array('term' => "me", 'count' => 0, 'display' => "Me"), array('term' => "others", 'count' => 0, 'display' => "Others")), 'owner-filter-selected' => isset($options['owner']) && strlen($options['owner']) > 0 ? $options['owner'] : 'all', 'tagsonly' => isset($options['tagsonly']) && $options['tagsonly'] == true ? true : Null, 'sort' => isset($options['sort']) && strlen($options['sort']) > 0 ? $options['sort'] : 'score', 'license' => isset($options['license']) && strlen($options['license']) > 0 ? $options['license'] : 'all'); if (strlen($query_string) <= 0) { return $result; } // 1- Get main facet // ------------------------------------------------------------------------------------------ $records = array(); $elasticaClient = PluginSearchElasticsearch::make_client(); $elasticaIndex = $elasticaClient->getIndex(get_config_plugin('search', 'elasticsearch', 'indexname')); $elasticaQueryString = new \Elastica\Query\QueryString(); $elasticaAnalyzer = get_config_plugin('search', 'elasticsearch', 'analyzer'); $elasticaQueryString->setAnalyzer($elasticaAnalyzer); $elasticaQueryString->setDefaultOperator('AND'); $elasticaQueryString->setQuery($query_string); // if tags only => set fields to tags if ($result['tagsonly'] === true) { $elasticaQueryString->setFields(array('tags')); } // Create the $elasticaQuery object $elasticaQuery = new \Elastica\Query(); $elasticaQuery->setFrom($offset); $elasticaQuery->setLimit($limit); $elasticaQuery->setQuery($elasticaQueryString); $elasticaFilterAnd = new \Elastica\Filter\BoolAnd(); // Apply ACL filters $elasticaFilterACL = new ElasticsearchFilterAcl($USER); $elasticaFilterAnd->addFilter($elasticaFilterACL); $elasticaQuery->setFilter($elasticaFilterAnd); // Define a new facet: mainFacetTerm - WARNING: don't forget to apply the same filter to the facet $elasticaFacet = new \Elastica\Facet\Terms('mainFacetTerm'); $elasticaFacet->setField('mainfacetterm'); $elasticaFacet->setOrder('count'); $elasticaFacet->setFilter($elasticaFilterAnd); $elasticaQuery->addFacet($elasticaFacet); $elasticaResultSet = $elasticaIndex->search($elasticaQuery); $result['totalresults'] = $elasticaResultSet->getTotalHits(); $elasticaFacets = $elasticaResultSet->getFacets(); $facets = self::process_facets($elasticaFacets['mainFacetTerm']['terms']); if (count($facets) == 0) { return $result; } array_walk($result['facets'], 'self::process_tabs', $facets); if ($result['selected'] === false || $facets[$result['selected']] == 0) { $result['selected'] = self::get_selected_facet($result['facets']); } // 2- Retrieve results of selected facet // ------------------------------------------------------------------------------------------ $elasticaFilterType = new \Elastica\Filter\Term(array('mainfacetterm' => $result['selected'])); $elasticaFilterAnd->addFilter($elasticaFilterType); $elasticaQuery->setFilter($elasticaFilterAnd); // Define a new facet: secFacetTerm - WARNING: don't forget to apply the same filter to the facet $elasticaFacet = new \Elastica\Facet\Terms('secFacetTerm'); $elasticaFacet->setField('secfacetterm'); $elasticaFacet->setOrder('count'); $elasticaFacet->setFilter($elasticaFilterAnd); $elasticaQuery->addFacet($elasticaFacet); // Sorting // Sorting is defined on a per field level, so we must make sure the field exists in the mapping $sort = explode('_', $result['sort']); if ($sort[0] == 'score') { $sort[0] = '_score'; } // set the second column to sort by the score (to break any 'ties'). $elasticaQuery->setSort(array(array($sort[0] => array('order' => isset($sort[1]) ? $sort[1] : 'desc')), array('_score' => array('order' => 'desc')))); $elasticaResultSet = $elasticaIndex->search($elasticaQuery); $result['count'] = $elasticaResultSet->getTotalHits(); $elasticaFacets = $elasticaResultSet->getFacets(); $facets = $elasticaFacets['secFacetTerm']['terms']; $facets = self::process_facets($elasticaFacets['secFacetTerm']['terms']); array_walk($result['content-filter'], 'self::process_tabs', $facets); // set the count of "all" to the total hits $result['content-filter'][0]['count'] = $result['count']; // 3- Apply filters and retrieve final results // ------------------------------------------------------------------------------------------ // Apply Content filter if different from "all" if ($result['content-filter-selected'] != 'all') { $elasticaFilterContent = new \Elastica\Filter\Term(array('secfacetterm' => $result['content-filter-selected'])); $elasticaFilterAnd->addFilter($elasticaFilterContent); } // Apply Owner filter if different from "all" if ($result['owner-filter-selected'] != 'all') { $uid = $USER->get('id'); $elasticaFilterOwner = new \Elastica\Filter\Term(array('owner' => $uid)); if ($result['owner-filter-selected'] == 'others') { $elasticaFilterOwner = new \Elastica\Filter\BoolNot($elasticaFilterOwner); } $elasticaFilterAnd->addFilter($elasticaFilterOwner); } // Apply license filter if different from "all" if ($result['license'] != 'all') { $elasticaFilterLicense = new \Elastica\Filter\Term(array('license' => $result['license'])); $elasticaFilterAnd->addFilter($elasticaFilterLicense); } $elasticaQuery->setFilter($elasticaFilterAnd); $elasticaResultSet = $elasticaIndex->search($elasticaQuery); $elasticaResults = $elasticaResultSet->getResults(); $result['count'] = $elasticaResultSet->getTotalHits(); foreach ($elasticaResults as $elasticaResult) { $tmp = array(); $tmp['type'] = $elasticaResult->getType(); $ES_class = 'ElasticsearchType_' . $tmp['type']; $tmp = $tmp + $elasticaResult->getData(); // Get all the data from the DB table $dbrec = $ES_class::getRecordDataById($tmp['type'], $tmp['id']); if ($dbrec) { $tmp['db'] = $dbrec; $tmp['db']->deleted = false; } else { // If the record has been deleted, so just pass the cached data // from the search result. Let the template decide how to handle // it. $tmp['db'] = (object) $tmp; $tmp['db']->deleted = true; } $records[] = $tmp; } $result['data'] = $records; return $result; }
/** * Main method to make a search */ public function search() { $this->getSearchFields(); $word = JRequest::getString('searchword', null, 'get'); $offset = JRequest::getInt('start', 0, 'get'); $limit = JRequest::getInt('limit', 10, 'get'); if ($limit == 0) { // no limit $limit = 10000; } $this->getSearchAreas(); $elasticaQueryString = new \Elastica\Query\QueryString(); // Log search word only on the first page if ($offset == 0) { SearchHelper::logSearch($word); } // Convert accents $word = htmlentities($word, ENT_NOQUOTES, 'utf-8'); $word = preg_replace('#\\&([A-za-z])(?:uml|circ|tilde|acute|grave|cedil|ring)\\;#', '\\1', $word); $word = preg_replace('#\\&([A-za-z]{2})(?:lig)\\;#', '\\1', $word); $word = preg_replace('#\\&[^;]+\\;#', '', $word); // Check if there are quotes ( for exact search ) $exactSearch = false; if (strlen($word) > 1 && $word[0] == '"' && $word[strlen($word) - 1] == '"') { $exactSearch = true; $word = substr($word, 1, strlen($word) - 2); // Remove external " } $word = Elastica\Util::replaceBooleanWordsAndEscapeTerm($word); // Escape ElasticSearch specials char if ($exactSearch) { $word = '"' . $word . '"'; } if ($word == "") { $word = "*"; } $elasticaQueryString->setQuery($word); //Create the actual search object with some data. $elasticaQuery = new Elastica\Query(); $elasticaQuery->setQuery($elasticaQueryString); if (ElasticSearchConfig::getHighLigthEnable()) { $fields = $this->getHighlightFields(); $hlfields = array(); foreach ($fields as $field) { foreach ($field as $highlight) { $hlfields[] = array($highlight => array('fragment_size' => 1000, 'number_of_fragments' => 1)); } } $highlightFields = array('pre_tags' => array(ElasticSearchConfig::getHighLigthPre()), 'post_tags' => array(ElasticSearchConfig::getHighLigthPost()), "order" => "score", 'fields' => $hlfields); $elasticaQuery->setHighlight($highlightFields); } // Set offset and limit for pagination $elasticaQuery->setFrom($offset); $elasticaQuery->setLimit($limit); //Create a filter for _type $elasticaFilterype = $this->createFilterType($this->areas); // Add filter to the search object. $elasticaQuery->setFilter($elasticaFilterype); //Search on the index. $elasticaResultSet = $this->elasticaIndex->search($elasticaQuery); $this->results = $elasticaResultSet->getResults(); $this->totalHits = $elasticaResultSet->getTotalHits(); }