public function testFuzzyWithFacets() { $index = $this->_createIndex(); $type = $index->getType('test'); $doc = new Document(1, array('name' => 'Basel-Stadt')); $type->addDocument($doc); $doc = new Document(2, array('name' => 'New York')); $type->addDocument($doc); $doc = new Document(3, array('name' => 'Baden')); $type->addDocument($doc); $doc = new Document(4, array('name' => 'Baden Baden')); $type->addDocument($doc); $index->refresh(); $field = 'name'; $fuzzyQuery = new Fuzzy(); $fuzzyQuery->setField($field, 'Baden'); $facet = new \Elastica\Facet\Terms('test'); $facet->setField('name'); $query = new \Elastica\Query($fuzzyQuery); $query->addFacet($facet); $resultSet = $index->search($query); // Assert query worked ok $this->assertEquals(2, $resultSet->count()); // Check Facets $this->assertTrue($resultSet->hasFacets()); $facets = $resultSet->getFacets(); $this->assertEquals(2, $facets['test']['total']); }
/** * adds current attribute facet condition to product collection * * @return Hackathon_ElasticgentoCore_Model_Catalog_Layer_Filter_Attribute */ public function addFacetToCollection() { $facet = new \Elastica\Facet\Terms($this->getAttributeModel()->getAttributeCode()); $facet->setField($this->getAttributeModel()->getAttributeCode()); $facet->setSize(10); $this->getLayer()->getProductCollection()->addFacet($facet); return $this; }
/** * * @see FacetInterface::getFacet */ public function getFacet($fieldName, \Elastica\Filter\AbstractFilter $mainFilter) { $rawFieldName = $this->getRawFieldName($fieldName); $mainFilter = $this->prepareMainFilter($mainFilter, $rawFieldName); $facet = new \Elastica\Facet\Terms($fieldName); $facet->setField($rawFieldName); $facet->setSize($this->options['size']); $facet->setFilter($mainFilter); return $facet; }
/** * Adds facet condition to product collection. * * @return Hackathon_ElasticgentoCore_Model_Catalog_Layer_Filter_Category * @todo add filter for current category childen */ public function addFacetToCollection() { /** @var $category Mage_Catalog_Model_Category */ #$category = $this->getCategory(); #$childrenCategories = $category->getChildrenCategories(); /** @todo refactor */ #$useFlat = (bool)Mage::getStoreConfig('catalog/frontend/flat_catalog_category'); #$categories = ($useFlat) ? array_keys($childrenCategories) : array_keys($childrenCategories->toArray()); $facet = new \Elastica\Facet\Terms('categories'); $facet->setField('categories'); $facet->setSize(10); $this->getLayer()->getProductCollection()->addFacet($facet); return $this; }
/** * 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; }
/** * @param AbstractElasticaSearcher $searcher * @param Request $request * @param RenderContext $context */ protected function applySearchParams(AbstractElasticaSearcher $searcher, Request $request, RenderContext $context) { // Retrieve the search parameters $queryString = trim($request->query->get('query')); $queryType = $request->query->get('type'); $lang = $request->getLocale(); $context['q_query'] = $queryString; $context['q_type'] = $queryType; $searcher->setData($this->sanitizeSearchQuery($queryString))->setContentType($queryType)->setLanguage($lang); // Facets $query = $searcher->getQuery(); $facetTerms = new \Elastica\Facet\Terms('type'); $facetTerms->setField('type'); $query->addFacet($facetTerms); // Aggregations $termsAggregation = new Terms('type'); $termsAggregation->setField('type'); $query->addAggregation($termsAggregation); }
/** * get attribute sets for current collection * * @return mixed */ public function getSetIds() { if (false == $this->isLoaded()) { $tmpSize = $this->getPageSize(); $this->setPageSize(0); $facet = new \Elastica\Facet\Terms('attribute_set_id'); $facet->setField('attribute_set_id'); $facet->setSize(10); $this->addFacet($facet); $this->load(); $this->removeFacet($facet->getName()); $this->setPageSize($tmpSize); $this->_setIsLoaded(false); } if (0 == count($this->_setIds)) { foreach ($this->_responseFacets['attribute_set_id']['terms'] as $term) { $this->_setIds[$term['term']] = $term['term']; } } return $this->_setIds; }
/** * @param string $q * @param array $params * @return array */ protected function _getAllFacets($q, array $params) { $facets = array(); $hasStats = isset($params['stats']) && isset($params['stats']['fields']) && !empty($params['stats']['fields']); if ($hasStats) { foreach ($params['stats']['fields'] as $field) { $facet = new \Elastica\Facet\Statistical($field); $facet->setParam('field', $field); $facets[] = $facet; } } if (isset($params['facets']) && !empty($params['facets'])) { $properties = $this->_getIndexProperties(); $filters = isset($params['filters']) ? $params['filters'] : array(); foreach ($params['facets'] as $field => $conds) { $queryFilter = null; if (array_key_exists($field, $filters)) { $_params = $params; #AM unset comment out for ATM (Custom Code). Need to test for other clients // unset($_params['filters'][$field]); $queryFilter = new \Elastica\Filter\Query($this->_getFilteredQuery($q, $_params)); } if (null === $conds) { // Terms Facet if (!$hasStats && array_key_exists($field, $properties)) { $facet = new \Elastica\Facet\Terms($field); if ($properties[$field]['type'] == 'multi_field') { $field .= '.untouched'; } $facet->setField($field)->setAllTerms(true)->setSize($this->getFacetsMaxSize()); if ($queryFilter) { $facet->setGlobal()->setFilter($queryFilter); } $facets[] = $facet; } } elseif (is_array($conds)) { if (isset($conds[0]['from']) && isset($conds[0]['to'])) { if (!$hasStats) { // Range Facet $facet = new \Elastica\Facet\Range($field); $facet->setField($field)->setRanges($this->_helper->_prepareRanges($conds)); $facets[] = $facet; } } else { foreach ($conds as $cond) { // Query Facet $query = $this->_helper->_prepareQuery($field, $cond); $facet = new \Elastica\Facet\Query($query); $facet->setQuery(new \Elastica\Query\QueryString($query)); if ($queryFilter) { $facet->setGlobal()->setFilter($queryFilter); } $facets[] = $facet; } } } } } return $facets; }
/** * * Add facets on elastic query object * @param \Elastica\Query $query * @param array $options * @param \Elastica\Filter\AbstractFilter $mainFilter */ protected function addFacets(\Elastica\Query $query, $options = array(), \Elastica\Filter\AbstractFilter $mainFilter = null) { // module facet (note: would be less confusing to give another name instead of _type) if (!empty($options['apply_module_facet'])) { $typeFacet = new \Elastica\Facet\Terms('_type'); $typeFacet->setField('_type'); // need to add filter for facet too if (isset($mainFilter)) { $typeFacet->setFilter($mainFilter); } $query->addFacet($typeFacet); } // handle secondary facets $this->facetHandler->addFacets($query, $options, $mainFilter); }
public function search($queryString, $opts, $highlight) { $query = new \Elastica\Query(); list($searchQuery, $highlights) = $this->parseQueryString($queryString, $opts); $query->setQuery($searchQuery); $language = new \Elastica\Facet\Terms('language'); $language->setField('language'); $language->setSize(500); $query->addFacet($language); $group = new \Elastica\Facet\Terms('group'); $group->setField('group'); // Would like to prioritize the top level groups and not show subgroups // if the top group has only few hits, but that doesn't seem to be possile. $group->setSize(500); $query->addFacet($group); $query->setSize($opts['limit']); $query->setFrom($opts['offset']); // BoolAnd filters are executed in sequence per document. Bool filters with // multiple must clauses are executed by converting each filter into a bit // field then anding them together. The latter is normally faster if either // of the subfilters are reused. May not make a difference in this context. $filters = new \Elastica\Filter\Bool(); $language = $opts['language']; if ($language !== '') { $languageFilter = new \Elastica\Filter\Term(); $languageFilter->setTerm('language', $language); $filters->addMust($languageFilter); } $group = $opts['group']; if ($group !== '') { $groupFilter = new \Elastica\Filter\Term(); $groupFilter->setTerm('group', $group); $filters->addMust($groupFilter); } // Check that we have at least one filter to avoid invalid query errors. if ($language !== '' || $group !== '') { $query->setPostFilter($filters); } list($pre, $post) = $highlight; $query->setHighlight(array('pre_tags' => array($pre), 'post_tags' => array($post), 'fields' => $highlights)); try { return $this->getType()->getIndex()->search($query); } catch (\Elastica\Exception\ExceptionInterface $e) { throw new TTMServerException($e->getMessage()); } }