Drupal: Customizing Apachesolr Autocomplete feature for content-type wise grouping of keyword suggestions.

Issue: In Drupal, can we group ApacheSolr search autocomplete suggestions bundle wise?
For example, if we have three bundle types, those are article, product and company. When we type a keyword in the search box, it should give us the options to search in keyword in article, keyword in product and keyword in company. Also, we need a separate suggestion count for each bundle. There is a dropdown box for listing bundle type options on the right side of the searchbox. We used Custom Search module for displaying this dropdownbox as an advanced search criteria.

Solution:
We can achieve this option by overriding Apachesolr Autocomplete module by customizing the ApacheSolr Search Query.
Please see the modified ‘apachesolr_autocomplete_suggest’ function from apachesolr_autocomplete.module.


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);

// This hook allows modules to modify the query and params objects.

drupal_alter('apachesolr_query', $query);
if (!$query) {
return array();
}
apachesolr_search_add_spellcheck_params($query);
foreach ($params as $param => $paramValue) {
$query->addParam($param, $paramValue);
}
apachesolr_search_add_boost_params($query);

// Query Solr

$response = $query->search($keys);

// Loop through requested fields and get suggestions.

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_UNICODE_WORD_BOUNDARY .']+/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.90;
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);
/* Here our custom code starts */
$suggkey = $suggestion;

// Returns the basic set of parameters for the Solr query.
$suggparams = apachesolr_autocomplete_basic_params(0.2);
$suggparams['facet.prefix'] = $suggkey;
$suggquery = apachesolr_drupal_query($suggkey);
drupal_alter('apachesolr_query', $suggquery);
$suggparam = array();
foreach ($suggparams as $suggparam => $suggparamValue) {
$suggquery->addParam($suggparam, $suggparamValue);
}

// Specify bundle types as facet query parameters for determining counts.
$suggquery->addParam('facet.query', 'bundle:article);
$suggquery->addParam('facet.query', 'bundle:product);
$suggquery->addParam('facet.query', 'bundle:company);

// Provides a content search implementation for node content for use with the Apache Solr search application.
apachesolr_search_add_boost_params($suggquery);
$suggresponse = $suggquery->search($suggkey);

// Retrieve the unique count for each bundle type.
$articlecount = $suggresponse->facet_counts->facet_queries->{'bundle:article'};
$productcount = $suggresponse->facet_counts->facet_queries->{'bundle:product'};
$companycount = $suggresponse->facet_counts->facet_queries->{'bundle:company’};

// Add into suggestions array
$suggestions['*' . $suggestion"] = theme('apachesolr_autocomplete_highlight', array('keys' => $orig_keys, 'suggestion' => $suggestion, 'count' => $articlecount, 'bundle_suggest' => 'article'));
$suggestions['*' . $suggestion"] = theme('apachesolr_autocomplete_highlight', array('keys' => $orig_keys, 'suggestion' => $suggestion, 'count' => $productcount, 'bundle_suggest' => 'product'));
$suggestions['*' . $suggestion"] = theme('apachesolr_autocomplete_highlight', array('keys' => $orig_keys, 'suggestion' => $suggestion, 'count' => $companycount, 'bundle_suggest' => 'company’));

/* Here custom code ends*/
}
}
}
}
return array(
'suggestions' => $suggestions,
'response' => &$response
);
}

This entry was posted in Drupal Developer Notes. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *