/** * Prepares the {@link SearchQuery}. Handles taking request arguments and * generating the filters and excludes to manipulate the search query. * * @return SearchQuery */ protected function prepareQuery() { $params = $this->getSearchParams(); $query = new SearchQuery(); // Filters $query->search($params['q']); // Permission checks. CanView* checks are really basic, don't check for // inheritance or enforce visibility for admins or other logged-in // members (based on their many-many relationships). $query->exclude('SiteTree_ShowInSearch', false); $query->exclude('SiteTree_CanViewType', 'OnlyTheseUsers'); $query->exclude('SiteTree_CanViewType', 'LoggedInUsers'); // $query->filter('..', true) return $query; }
/** * Performs the search against the snippets in the system * * @param {string} $keywords Keywords to search for * @param {int} $languageID Language to filter to * @param {int} $folderID Folder to filter to * @return {DataList} Data list pointing to the snippets in the results */ public function doSnippetSearch($keywords, $languageID = false, $folderID = false) { $searchIndex = singleton('CodeBankSolrIndex'); $searchQuery = new SearchQuery(); $searchQuery->classes = array(array('class' => 'Snippet', 'includeSubclasses' => true)); //Add language filtering if ($languageID !== false && $languageID > 0) { $searchQuery->filter('Snippet_LanguageID', $languageID); } //Add language filtering if ($folderID !== false && $folderID > 0) { $searchQuery->filter('Snippet_FolderID', $folderID); } //Configure search $searchQuery->search($keywords, null, array('Snippet_Title' => 2, 'Snippet_Description' => 1)); return $searchIndex->search($searchQuery, null, null)->Matches->getList(); }
/** * @param string $keywords * @param array $filters * @return array */ public function suggestWithResults($keywords, array $filters = array()) { $limit = (int) ShopSearch::config()->sayt_limit; // process the keywords a bit $terms = preg_split('/\\s+/', trim(strtolower($keywords))); $lastTerm = count($terms) > 0 ? array_pop($terms) : ''; $prefix = count($terms) > 0 ? implode(' ', $terms) . ' ' : ''; //$terms[] = $lastTerm; $terms[] = $lastTerm . '*'; // this allows for partial words to still match // convert that to something solr adapater can handle $query = new SearchQuery(); $query->search('+' . implode(' +', $terms)); $params = array('sort' => 'score desc', 'facet' => 'true', 'facet.field' => '_autocomplete', 'facet.limit' => ShopSearch::config()->suggest_limit, 'facet.prefix' => $lastTerm); // $facetSpec = array( // '_autocomplete' => array( // 'Type' => ShopSearch::FACET_TYPE_LINK, // 'Label' => 'Suggestions', // 'Source' => '_autocomplete', // ), // ); // // Debug::dump($query); // // $search = $this->search($query, 0, $limit, $params, $facetSpec); // Debug::dump($search); // $prodList = $search->Matches; // // $suggestsion = array(); //// if ($) $service = $this->getService(); SearchVariant::with(count($query->classes) == 1 ? $query->classes[0]['class'] : null)->call('alterQuery', $query, $this); $q = $terms; $fq = array(); // Build the search itself // foreach ($query->search as $search) { // $text = $search['text']; // preg_match_all('/"[^"]*"|\S+/', $text, $parts); // // $fuzzy = $search['fuzzy'] ? '~' : ''; // // foreach ($parts[0] as $part) { // $fields = (isset($search['fields'])) ? $search['fields'] : array(); // if(isset($search['boost'])) $fields = array_merge($fields, array_keys($search['boost'])); // if ($fields) { // $searchq = array(); // foreach ($fields as $field) { // $boost = (isset($search['boost'][$field])) ? '^' . $search['boost'][$field] : ''; // $searchq[] = "{$field}:".$part.$fuzzy.$boost; // } // $q[] = '+('.implode(' OR ', $searchq).')'; // } // else { // $q[] = '+'.$part.$fuzzy; // } // } // } // Filter by class if requested $classq = array(); foreach ($query->classes as $class) { if (!empty($class['includeSubclasses'])) { $classq[] = 'ClassHierarchy:' . $class['class']; } else { $classq[] = 'ClassName:' . $class['class']; } } if ($classq) { $fq[] = '+(' . implode(' ', $classq) . ')'; } // Filter by filters foreach ($query->require as $field => $values) { $requireq = array(); foreach ($values as $value) { if ($value === SearchQuery::$missing) { $requireq[] = "(*:* -{$field}:[* TO *])"; } elseif ($value === SearchQuery::$present) { $requireq[] = "{$field}:[* TO *]"; } elseif ($value instanceof SearchQuery_Range) { $start = $value->start; if ($start === null) { $start = '*'; } $end = $value->end; if ($end === null) { $end = '*'; } $requireq[] = "{$field}:[{$start} TO {$end}]"; } else { $requireq[] = $field . ':"' . $value . '"'; } } $fq[] = '+(' . implode(' ', $requireq) . ')'; } foreach ($query->exclude as $field => $values) { $excludeq = array(); $missing = false; foreach ($values as $value) { if ($value === SearchQuery::$missing) { $missing = true; } elseif ($value === SearchQuery::$present) { $excludeq[] = "{$field}:[* TO *]"; } elseif ($value instanceof SearchQuery_Range) { $start = $value->start; if ($start === null) { $start = '*'; } $end = $value->end; if ($end === null) { $end = '*'; } $excludeq[] = "{$field}:[{$start} TO {$end}]"; } else { $excludeq[] = $field . ':"' . $value . '"'; } } $fq[] = ($missing ? "+{$field}:[* TO *] " : '') . '-(' . implode(' ', $excludeq) . ')'; } // if(!headers_sent()) { // if ($q) header('X-Query: '.implode(' ', $q)); // if ($fq) header('X-Filters: "'.implode('", "', $fq).'"'); // } $params = array_merge($params, array('fq' => implode(' ', $fq))); $res = $service->search(implode(' ', $q), 0, $limit, $params, Apache_Solr_Service::METHOD_POST); $results = new ArrayList(); if ($res->getHttpStatus() >= 200 && $res->getHttpStatus() < 300) { foreach ($res->response->docs as $doc) { $result = DataObject::get_by_id($doc->ClassName, $doc->ID); if ($result) { $results->push($result); } } $numFound = $res->response->numFound; } else { $numFound = 0; } $ret = array(); $ret['products'] = new PaginatedList($results); $ret['products']->setLimitItems(false); $ret['products']->setTotalItems($numFound); $ret['products']->setPageStart(0); $ret['products']->setPageLength($limit); // Facets (this is how we're doing suggestions for now... $ret['suggestions'] = array(); if (isset($res->facet_counts->facet_fields->_autocomplete)) { foreach ($res->facet_counts->facet_fields->_autocomplete as $term => $count) { $ret['suggestions'][] = $prefix . $term; } } // Suggestions (requires custom setup, assumes spellcheck.collate=true) // if(isset($res->spellcheck->suggestions->collation)) { // $ret['Suggestion'] = $res->spellcheck->suggestions->collation; // } return $ret; }
function testHighlightQueryOnBoost() { $serviceMock = $this->getServiceMock(); Phockito::when($serviceMock)->search(anything(), anything(), anything(), anything(), anything())->return($this->getFakeRawSolrResponse()); $index = new SolrIndexTest_FakeIndex(); $index->setService($serviceMock); // Search without highlighting $query = new SearchQuery(); $query->search('term', null, array('Field1' => 1.5, 'HasOneObject_Field1' => 3)); $index->search($query); Phockito::verify($serviceMock)->search('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)', anything(), anything(), not(hasKeyInArray('hl.q')), anything()); // Search with highlighting $query = new SearchQuery(); $query->search('term', null, array('Field1' => 1.5, 'HasOneObject_Field1' => 3)); $index->search($query, -1, -1, array('hl' => true)); Phockito::verify($serviceMock)->search('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)', anything(), anything(), hasKeyInArray('hl.q'), anything()); }
/** * Builds a search query from a give search term. * @return SearchQuery */ protected function getSearchQuery($keywords) { $categoryIDs = array(); $categoryFilterID = $this->request->requestVar(self::$search_category_key); $categories = $this->Categories(); if ($categories->count() == 0) { $categories = FAQ::getRootCategory()->Children(); } $filterCategory = $categories->filter('ID', $categoryFilterID)->first(); $categoryIDs = array(); if ($filterCategory && $filterCategory->exists()) { $categoryIDs = $this->getSelectedIDs(array($filterCategory)); } else { $categoryIDs = $this->Categories()->column('ID'); } $query = new SearchQuery(); $query->classes = self::$classes_to_search; if (count($categoryIDs) > 0) { $query->filter('FAQ_Category_ID', array_filter($categoryIDs, 'intval')); } $query->search($keywords); // Artificially lower the amount of results to prevent too high resource usage. // on subsequent canView check loop. $query->limit(100); return $query; }