hook_apachesolr_modify_query(&$query, &$params, $caller);

Any module performing a search should call apachesolr_modify_query($query, $params, 'modulename'). That function then invokes this hook. It allows modules to modify the query object and params array. $caller indicates which module is invoking the hook.

Example:

function my_module_apachesolr_modify_query(&$query, &$params, $caller) {
   // I only want to see articles by the admin!
   $query->add_filter("uid", 1);          
}

Also we can add "query" filters .An example is :

$query->add_filter("_query_", '{!geofilt sfield=location pt=36.7344685,-6.43353209 d=10}');
hook_apachesolr_cck_fields_alter(&$mappings)

Add or alter index mappings for CCK types. The default mappings array handles just
text and integer fields with option widgets:

$mappings['text'] = array(
  'optionwidgets_select' => array('callback' => '', 'index_type' => 'string', 'facets' => TRUE),
  'optionwidgets_buttons' => array('callback' => '', 'index_type' => 'string', 'facets' => TRUE),
  'optionwidgets_onoff' => array('callback' => '', 'index_type' => 'string', 'facets' => TRUE),
);
$mappings['number_integer'] = array(
  'optionwidgets_select' => array('callback' => '', 'index_type' => 'sint', 'facets' => TRUE),
  'optionwidgets_buttons' => array('callback' => '', 'index_type' => 'sint', 'facets' => TRUE),
  'optionwidgets_onoff' => array('callback' => '', 'index_type' => 'sint', 'facets' => TRUE),
);

This array has the form $mappings[$field_data_type][$field_widget_type]. In your _alter hook implementation you can add additional field types such as:

$mappings['number_integer']['number'] = array('callback' => '', 'index_type' => 'integer');

You can also add a mapping for a specific field. This will take precedence over any
mapping for a general field type. A field-specific mapping would look like:

$mappings['per-field']['field_model_name'] = array('callback' => '', 'index_type' => 'string');

or

$mappings['per-field']['field_model_price'] = array('callback' => '', 'index_type' => 'float');

If a callback is provided, it should have the signature my_callback($node, $cck_field_name), This function will be called before hook_apachesolr_update_index and should return a list of the value(s) which will be indexed in that field.

hook_apachesolr_node_exclude($node)
This is invoked by apachesolr.module for each node to be added to the index - if any module returns TRUE, the node is skipped for indexing. For example, this is used by apachesolr_search module to exclude certain node types from the index.
hook_apachesolr_update_index(&$document, $node)
Allows a module to change the contents of the $document object before it is sent to the Solr Server. To add a new field to the document, you should generally use one of the pre-defined dynamic fields. Follow the naming conventions for the type of data being added based on the schema.xml file.
hook_apachesolr_search_result_alter(&$doc)
The is invoked by apachesolr_search.module for each document returned in a search - new in 6.x-dev as a replacement for the call to hook_nodeapi().
hook_apachesolr_process_results(&$results)
Invoked by apachesolr_search.module on the results array, after hook_apachesolr_search_result_alter above.
hook_apachesolr_sort_links_alter(&$sort_links)
Called by the sort link block code. Allows other modules to modify, add or remove sorts.

This post may be helpful: Using hook_apachesolr_cck_field_mappings() [Updated on April 20, 2010]

Comments

pokadan’s picture

I believe there's been an api change with the latest release.
Basically add_field() member function changed to add_filter()

toemaz’s picture

The handbook page has been updated.

emackn’s picture

So does "Any module performing a search" imply that your module is implementing hook_search?

aufumy’s picture

hook_search is to define a new type of search, so it would not mean that.

I believe it meant if your module is calling apachesolr_search_execute($keys, $filters, $solrsort, $base_path = '', $page = 0, $caller = 'apachesolr_search')

vikingjs’s picture

It would be really, really nice to have a link to any documentation on the interface to the $query object referred to here (Drupal_Solr_Query_Interface). I spent an afternoon searching and wound up reading the module source code.

Edited to add another 'really'. Still searching days later. What's in the query? What's in params? Why are my added filters lost when I set aliases? Is it a bug or am I using it wrong? Heck if I know. It has to be written down somewhere.

MA-Hugh’s picture

I have been searching for implementation on doing a simple search outside of the core just for a news area, so far I can return ALL results but the keys aren't working and nowhere can I find proper documentation on this.

Could someone shed some light on what I am doing wrong?

// Set the defaults
// $keys comes from the user input ie $keys = 'foo' - I am guessing on this one.
// score desc is the fake score field in solr
// return just the nid,title,teaser,url
// return 10 rows starting at 0
	$output = '';
	$query = apachesolr_drupal_query($keys, $filters = 'score desc');
  $query->add_filter('type', 'story');
	$params = array(
		'fl' => 'nid,title,teaser,url',
		'rows' => variable_get('project_solr_block_rows', 10),
		'start' => 0,
	);

// Get the solr isntance
	$solr = apachesolr_get_solr();

// Call modify incase there is any restrictions called by anything else
	apachesolr_modify_query($query, $params, 'apachesolr_search');
	if (!$query) {
		return '';
	}

// Perform the search
	$response = $solr->search($query, $params['start'], $params['rows'], $params);

// If solr is online then...
	if($response->getHttpStatus() == 200) {

// Get the total results
	$total = $response->response->numFound;

// If we have results generate output
		if ($total > 0) {
			foreach ($response->response->docs as $doc) {
				$output .= var_export($doc, TRUE);//theme_project_solr_link($doc);
			}
		}
		else {
// Print out  a friendly error if there are no results found
			$output .= t('Search term not found.');
		}
	}
	else
	{
// Print out my error this will go into the watchdog after development and display a friendly error
		$output .= t('Page error: '.$response->getHttpStatus());
	}

King regards,
Hugh Wood
Mastersallen.co.uk

ShaneOnABike’s picture

After developing some code for a website that we were building that required the integration of CCK types that were of type integer I thought I would post the following code to help others out.

CCK fields alter (CCK strings deal with these types out of the box but not for integers tragically)

function yourmodule_apachesolr_cck_fields_alter(&$mappings) {
  $mappings['number_integer'] = array(
   'optionwidgets_select' => array(
      // This function is called when teh facet is being indexed
      'indexing_callback' => 'yourmodule_cck_checklist_indexing_callback',
      // This function will get called when the facet links are displayed
      // in facet blocks at search time.
      'display_callback' => 'yourmodule_cck_checklist_display_callback',
     'index_type' => 'integer'),
   'optionwidgets_buttons' => array(
      'indexing_callback' => 'yourmodule_cck_checklist_indexing_callback',
      // This function will get called when the facet links are displayed
      // in facet blocks at search time.
      'display_callback' => 'olesolr_cck_checklist_display_callback',
      'index_type' => 'integer'),
  );
  return $mappings;
}

Next function renders the checklist block

function olesolr_cck_checklist_indexing_callback($node, $field_name, $cck_info) {
  // $fields is an array because we send back a key => value pair for every
  // value of the field.
  $fields = array();

  // Don't do anything if this node doesn't have this field.
  if (isset($node->$field_name)) {
    // Get the index key based on the $cck_info.
    $index_key = apachesolr_index_key($cck_info);
    //dsm($index_key);

    // Go through each item and setup the appropriate key
    foreach ($node->$field_name as $field) {
      foreach($field as $key => $value) {
        if ($index_value =  (isset($value) ? $value : FALSE)) {
          $fields[] = array(
            'key' => $index_key,
            'value' => $index_value,
          );
        }
      }
    }
  }
  return $fields;
}

Finally the display callback (which is pretty basic)

function yourmodule_cck_checklist_display_callback($facet, $options) {
  if (function_exists('content_format')) {
    return content_format($options['delta'], array('value' => $facet));
  }
  else {
    return $facet;
  }
}

scoff’s picture

I've moved from faceted_search to apachesolr and missed the faceted_search navigation blocks. Apachesolr only shows it's blocks on the search pages (search/apachesolr). This is a quick hack to perform a custom search and show the corresponding taxonomy facete block. (apachesolr 6.x-2.x-dev)


/* dirty hack to make apachesolr show the facetes block
*  it's hardcoded to initiate apachesolr search on a certain page (custom view at /store)
*  see in action here http://4soldo.ru/store (left sidebar)
*/

function forcesolr_init() {

	switch(arg(0)) {
		// see if we're on the right page
	    case 'store' :
		
		// get apachesolr query instance
		// function apachesolr_drupal_query($keys = '', $filters = '', $solrsort = '', $base_path = '')
		// don't forget the $browse_path
		$query = apachesolr_drupal_query('','','','search/apachsolr_search');
		// query params
		$params = array(
		'start' => 0,
		'rows' => 0,
		'facet' => 'true', // this one is important
		);
		// add all configured facetes to $params
		apachesolr_search_add_facet_params($params, $query);

		// add type filter (I only need 'store' content type)
		// 'fsl' doesn't mean anything or used anywhere else,
		// just like apachesolr_fsl below
		$params['fq']['fsl'][] = 'type:store';
		
		// once again, this time for blocks
		// without this blocks don't remember the filter
		$query->add_filter('type','store');		

		// This hook allows modules to modify the query and params objects.
		// Actually we need this to process $params['fq']['fsl'][]
		apachesolr_modify_query($query, $params, 'apachesolr_fsl');
		if (empty($query)) {
		  return;
		}

		// get solr object				
		$solr = apachesolr_get_solr();
	
		$result = $solr->search($query, 0, 0, $params);
		if(empty($result)) return;
		
		// time to check what we got from Solr
#		drupal_set_message('<pre>result' . print_r($result,true) . '</pre>');
		
		// get rid of unneeded 'type' facete (it's already set to 'store')
		// also I had to hide 'current search' block via block visibility options
		unset($result->facet_counts->facet_fields->type);
		
		// save the solr response so it can be used by blocks lates
		apachesolr_static_response_cache($result,'apachesolr_search');
		// cache the query info
		apachesolr_current_query($query);
		// rise the flag
		apachesolr_has_searched(TRUE);
	
	}

}

Here's the live page using this code: http://4soldo.ru/store (in russian)
The same result can be acheived with apachesolr_views, but it's for views 3 only.
Hope it helps someone.

stuchl4n3k’s picture

I am dealing with the same issue as MA-Hugh...