You are here

function apachesolr_autocomplete_suggest in Apache Solr Autocomplete 6

Same name and namespace in other branches
  1. 7.2 apachesolr_autocomplete.module \apachesolr_autocomplete_suggest()
  2. 7 apachesolr_autocomplete.module \apachesolr_autocomplete_suggest()
2 calls to apachesolr_autocomplete_suggest()
apachesolr_autocomplete_suggest_additional_term in ./apachesolr_autocomplete.module
Helper function that suggests additional terms to search for.
apachesolr_autocomplete_suggest_word_completion in ./apachesolr_autocomplete.module
Helper function that suggests ways to complete partial words.

File

./apachesolr_autocomplete.module, line 298
Alters search forms to suggest terms using Apache Solr using AJAX. Thanks to robertDouglass who contributed some of the code.

Code

function apachesolr_autocomplete_suggest($keys, $params, $orig_keys, $suggestions_to_return = 5) {
  $matches = array();
  $suggestions = array();
  $keys = trim($keys);

  // We need the keys array to make sure we don't suggest words that are already
  // in the search terms.
  $keys_array = explode(' ', $keys);
  $keys_array = array_filter($keys_array);

  // Query Solr for $keys so that suggestions will always return results.
  $query = apachesolr_drupal_query($keys);

  // Allow other modules to modify query.
  if (function_exists('apachesolr_modify_query')) {
    apachesolr_modify_query($query, $params, 'apachesolr_autocomplete');
    $apachesolr_version = '6.x-1.x';
  }
  else {

    // Assume we're running apachesolr 6.x-3.x
    // This hook allows modules to modify the query and params objects.
    drupal_alter('apachesolr_query', $query);
    $apachesolr_version = '6.x-3.x';
  }
  if (!$query) {
    return array();
  }
  if (function_exists('apachesolr_search_spellcheck_params')) {
    $params += apachesolr_search_spellcheck_params($query);
  }
  if (function_exists('apachesolr_search_add_spellcheck_params')) {
    apachesolr_search_add_spellcheck_params($query);
  }

  // Try to contact Solr.
  try {
    $solr = apachesolr_get_solr();
    if ($apachesolr_version == '6.x-1.x') {
      apachesolr_search_add_boost_params($params, $query, $solr);
    }
    else {
      foreach ($params as $param => $paramValue) {
        $query
          ->addParam($param, $paramValue);
      }
      apachesolr_search_add_boost_params($query);
    }
  } catch (Exception $e) {
    watchdog('Apache Solr', $e
      ->getMessage(), NULL, WATCHDOG_ERROR);
    return array();
  }

  // Query Solr
  if ($apachesolr_version == '6.x-1.x') {
    $response = $solr
      ->search($keys, $params['start'], $params['rows'], $params);
  }
  else {
    $response = $solr
      ->search($query, $params);
  }
  foreach ($params['facet.field'] as $field) {
    foreach ($response->facet_counts->facet_fields->{$field} as $terms => $count) {
      $terms = preg_replace('/[_-]+/', ' ', $terms);
      foreach (explode(' ', $terms) as $term) {
        if ($term = trim(preg_replace('/[' . PREG_CLASS_SEARCH_EXCLUDE . ']+/u', '', $term))) {
          if (isset($matches[$term])) {
            $matches[$term] += $count;
          }
          else {
            $matches[$term] = $count;
          }
        }
      }
    }
  }
  if (sizeof($matches) > 0) {

    // Eliminate suggestions that are stopwords or are already in the query.
    $matches_clone = $matches;
    $stopwords = apachesolr_autocomplete_get_stopwords();
    foreach ($matches_clone as $term => $count) {
      if (strlen($term) > 3 && !in_array($term, $stopwords) && !array_search($term, $keys_array)) {

        // Longer strings get higher ratings.
        $matches_clone[$term] += strlen($term);
      }
      else {
        unset($matches_clone[$term]);
        unset($matches[$term]);
      }
    }

    // Don't suggest terms that are too frequent (in >90% of results).
    $max_occurence = $response->response->numFound * 0.9;
    foreach ($matches_clone as $match => $count) {
      if ($count > $max_occurence) {
        unset($matches_clone[$match]);
      }
    }

    // The $count in this array is actually a score. We want the highest ones first.
    arsort($matches_clone);

    // Shorten the array to the right ones.
    $matches_clone = array_slice($matches_clone, 0, $suggestions_to_return, TRUE);

    // Add current search as suggestion if results > 0
    if ($response->response->numFound > 0 && $keys != '') {

      // Add * to array element key to force into a string, else PHP will
      // renumber keys that look like numbers on the returned array.
      $suggestions['*' . $keys] = array(
        'theme' => 'apachesolr_autocomplete_highlight',
        'keys' => $keys,
        'suggestion' => $keys,
        'count' => $response->response->numFound,
      );
    }

    // Build suggestions using returned facets
    foreach ($matches_clone as $match => $count) {
      if ($keys != $match) {
        $suggestion = trim($keys . ' ' . $match);

        // On cases where there are more than 3 keywords, omit displaying
        //  the count because of the mm settings in solrconfig.xml
        if (substr_count($suggestion, ' ') >= 2) {
          $count = 0;
        }
        if ($suggestion != '') {

          // Add * to array element key to force into a string, else PHP will
          // renumber keys that look like numbers on the returned array.
          $suggestions['*' . $suggestion] = array(
            'theme' => 'apachesolr_autocomplete_highlight',
            'keys' => $orig_keys,
            'suggestion' => $suggestion,
            'count' => $count,
          );
        }
      }
    }
  }
  return array(
    'suggestions' => $suggestions,
    'response' => &$response,
  );
}