Example #1
0
 /**
  * Actually process and submit the search
  *
  * @access  public
  * @param   bool   $returnIndexErrors  Should we die inside the index code if
  *                                     we encounter an error (false) or return
  *                                     it for access via the getIndexError()
  *                                     method (true)?
  * @param   bool   $recommendations    Should we process recommendations along
  *                                     with the search itself?
  * @return  object solr result structure (for now)
  */
 public function processSearch($returnIndexErrors = false, $recommendations = false)
 {
     global $timer;
     global $analytics;
     // Our search has already been processed in init()
     $search = $this->searchTerms;
     // Build a recommendations module appropriate to the current search:
     if ($recommendations) {
         $this->initRecommendations();
     }
     $timer->logTime("initRecommendations");
     // Tag searches need to be handled differently
     if (count($search) == 1 && isset($search[0]['index']) && $search[0]['index'] == 'tag') {
         // If we managed to find some tag matches, let's override the search
         // array.  If we didn't find any tag matches, we should return an
         // empty record set.
         $newSearch = $this->processTagSearch($search[0]['lookfor']);
         $timer->logTime("process Tag search");
         // Save search so it displays correctly on the "no hits" page:
         $this->publicQuery = $search[0]['lookfor'];
         if (empty($newSearch)) {
             return array('response' => array('numFound' => 0, 'docs' => array()));
         } else {
             $search = $newSearch;
         }
     }
     // Build Query
     $query = $this->indexEngine->buildQuery($search);
     $timer->logTime("build query");
     if (PEAR_Singleton::isError($query)) {
         return $query;
     }
     // Only use the query we just built if there isn't an override in place.
     if ($this->query == null) {
         $this->query = $query;
     }
     // Define Filter Query
     $filterQuery = $this->hiddenFilters;
     //Remove any empty filters if we get them
     //(typically happens when a subdomain has a function disabled that is enabled in the main scope)
     foreach ($this->filterList as $field => $filter) {
         if (empty($field)) {
             unset($this->filterList[$field]);
         }
     }
     foreach ($this->filterList as $field => $filter) {
         foreach ($filter as $value) {
             $analytics->addEvent('Apply Facet', $field, $value);
             // Special case -- allow trailing wildcards:
             if (substr($value, -1) == '*') {
                 $filterQuery[] = "{$field}:{$value}";
             } elseif (preg_match('/\\A\\[.*?\\sTO\\s.*?]\\z/', $value)) {
                 $filterQuery[] = "{$field}:{$value}";
             } else {
                 if (!empty($value)) {
                     $filterQuery[] = "{$field}:\"{$value}\"";
                 }
             }
         }
     }
     // If we are only searching one field use the DisMax handler
     //    for that field. If left at null let solr take care of it
     if (count($search) == 1 && isset($search[0]['index'])) {
         $this->index = $search[0]['index'];
     }
     // Build a list of facets we want from the index
     $facetSet = array();
     if (!empty($this->facetConfig)) {
         $facetSet['limit'] = $this->facetLimit;
         foreach ($this->facetConfig as $facetField => $facetName) {
             $facetSet['field'][] = $facetField;
         }
         if ($this->facetOffset != null) {
             $facetSet['offset'] = $this->facetOffset;
         }
         if ($this->facetPrefix != null) {
             $facetSet['prefix'] = $this->facetPrefix;
         }
         if ($this->facetSort != null) {
             $facetSet['sort'] = $this->facetSort;
         }
     }
     $timer->logTime("create facets");
     // Build our spellcheck query
     if ($this->spellcheck) {
         if ($this->spellSimple) {
             $this->useBasicDictionary();
         }
         $spellcheck = $this->buildSpellingQuery();
         // If the spellcheck query is purely numeric, skip it if
         // the appropriate setting is turned on.
         if ($this->spellSkipNumeric && is_numeric($spellcheck)) {
             $spellcheck = "";
         }
     } else {
         $spellcheck = "";
     }
     $timer->logTime("create spell check");
     // Get time before the query
     $this->startQueryTimer();
     // The "relevance" sort option is a VuFind reserved word; we need to make
     // this null in order to achieve the desired effect with Solr:
     $finalSort = $this->sort == 'relevance' ? null : $this->sort;
     // The first record to retrieve:
     //  (page - 1) * limit = start
     $recordStart = ($this->page - 1) * $this->limit;
     $this->indexResult = $this->indexEngine->search($this->query, $this->index, $filterQuery, $recordStart, $this->limit, $facetSet, $spellcheck, $this->dictionary, $finalSort, $this->fields, $this->method, $returnIndexErrors);
     $timer->logTime("run solr search");
     // Get time after the query
     $this->stopQueryTimer();
     // How many results were there?
     if (!isset($this->indexResult['response']['numFound'])) {
         //An error occurred
         $this->resultsTotal = 0;
     } else {
         $this->resultsTotal = $this->indexResult['response']['numFound'];
     }
     // Process spelling suggestions if no index error resulted from the query
     if ($this->spellcheck && !isset($this->indexResult['error'])) {
         // Shingle dictionary
         $this->processSpelling();
         // Make sure we don't endlessly loop
         if ($this->dictionary == 'default') {
             // Expand against the basic dictionary
             $this->basicSpelling();
         }
     }
     // If extra processing is needed for recommendations, do it now:
     if ($recommendations && is_array($this->recommend)) {
         foreach ($this->recommend as $currentSet) {
             foreach ($currentSet as $current) {
                 $current->process();
             }
         }
     }
     //Add debug information to the results if available
     if ($this->debug) {
         $explainInfo = $this->indexResult['debug']['explain'];
         foreach ($this->indexResult['response']['docs'] as $key => $result) {
             if (array_key_exists($result['id'], $explainInfo)) {
                 $result['explain'] = $explainInfo[$result['id']];
                 $this->indexResult['response']['docs'][$key] = $result;
             }
         }
     }
     // Return the result set
     return $this->indexResult;
 }