I have a custom search form, and the form's execute function calls apachesolr_search_search_results(). One of the elements on the form is a drop-down to select which field to search (keyword, author, call number, etc), so I need to set 'qf'. I was able to replace 'qf' via hook_apachesolr_query_alter(), however I think the code would be improved if 'qf' could be passed in directly.

Thoughts? For executing a custom query (with appropriate defaults from the module), Is there a better entry point than apachesolr_search_search_results()?

Let me know if this isn't clear; I can try to post code for an example use case. Thanks!

Comments

nick_vh’s picture

What about hook_apachesolr_query_alter? You could do $query->addParam('qf', 'value'); isn't that direct enough?

Please explain in greater depth ;-)

grendzy’s picture

Here's an example (I trimmed out many of the #options for the sake of readability). hook_apachesolr_query_alter() absolutely works, but $form['values'] isn't in scope at that point so I have to rely on $_GET superglobals. It seems the API would be more convenient, and more complete, if 'qf' could be passed in apachesolr_search_search_results(). Again, if this is the wrong entry point for executing a custom query, please let me know.


/**
 * Form callback for search/site.
 */
function mymodule_form($form_state) {
  $form = array();
  if (user_is_logged_in()) {
    $form['#token'] = FALSE;
  }
  $form['#method'] = 'get';
  $form['query'] = array(
    '#type' => 'textfield',
    '#title' => t('Search'),
  );
  $form['type'] = array(
    '#type' => 'select',
    '#title' => t('by'),
    '#options' => array('author' => t('Author'), 'callnum' => t('Call Number')),
  );
  $form['format'] = array(
    '#type' => 'select',
    '#title' => t('in'),
    '#options' => array('all' => t('Everything'), 'movies' => t('Movies')),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Go'),
  );

  return $form;
}

/**
 * Submit handler for search/site.
 */
function mymodule_form_submit($form, &$form_state) {
  if (!empty($form_state['values']['query'])) {
    $form_state['storage']['results'] = mymodule_execute($form_state['values']);
  }
}

/**
 * Executes a Solr search.
 */
function mymodule_execute($values) {
  $search_page = apachesolr_search_page_load('core_search');
  $conditions = array();

  switch($values['format']) {
    case 'movies':
      $conditions['fq'] = 'ss_field_type:(dvd OR vhs)';
      break;
  }

  switch($values['type']) {
    case 'author':
      /*****  Feature request to set 'qf' here *****/
      $conditions['qf'] = 'tm_field_authors';
      /*********************************************/
      break;
  }

  $keys = array($values['query']);
  return apachesolr_search_search_results($keys, $conditions, $search_page);
}

wonder95’s picture

I'm doing the same thing, but I found by following the code that in your call to apachesolr_search_search_results you can pass the qf value as part of $conditions In my case, the values are coming from a field in a node that contains saved search data:

  $node = node_load($nid);
  $search_page = apachesolr_search_page_load('saved_search');
  $conditions = apachesolr_search_conditions_default($search_page);
  if (isset($node->ss_conditions[$node->language])) {
    $params = unserialize($node->ss_conditions[$node->language][0]['value']);
    if (isset($params['filters'])) {
      $filters = $params['filters'];
      foreach ($filters as $vid => $terms) {
        $conditions['fq'][] = $terms;
        $filter_parts = explode(':', $terms);
        $conditions['qf'][] = $filter_parts[0];
      }
    }
  }
  // Search solr using keys from ss_keys field in the saved_search node.
  $results = apachesolr_search_search_results($keys, $conditions, $search_page);

This successfully passes the values to the query as qf parameters. There are other issues I have yet to figure out, such as the value being placed in the query string twice (which doesn't effect search results), but this demonstrates how you can pass qf values w/o having to wait until the query_alter hook is fired.

nick_vh’s picture

Status: Active » Fixed
grendzy’s picture

Status: Fixed » Active

wonder95, I retested $conditions['qf']... and I'm still not seeing any effect. Can you check the Solr request.log, and post the log entry produced by your search?

From reading the source code of apachesolr_search_search_results() it seems clear the 'qf' key is never mentioned. The only parts of $conditions used are:

  • $conditions['apachesolr_search_sort']
  • $conditions['fq']
  • $conditions['f']
marblegravy’s picture

I agree with grendzy's analysis. At no stage is the 'qf' taken out of $conditions and applied to the query.

The only way I can get the 'qf' to take is with hook_apachesolr_query_alter() but then I run in to the issue of being unable to identify which search is currently running, or the context where the search is coming from. Which is where my other issue came from (#1976224: Can you tag individual searches per search in order to apply different filters to each?)

rblackmore’s picture

Issue summary: View changes

I'm having, what I believe, is a similar issue and I'm wondering if in the last few years there has been a more elegant solution to this problem.

Right now I have a custom module that basically does this:

  • implements hook_form_alter() to add a multi-site dropdown select to 'apachesolr_search_custom_page_search_form'
  • process results with hook_form_submit():
    • retrieves the current URL string: $get = json_decode($form_state['values']['get'], TRUE);
    • rewrite $get['f'] with the $form_state input (so either adding, changing or removing site hashes from/to $get['f')
    • overwrites $form_state['redirect']

I keep thinking there has to be a way to pass $form_state values directly into hook_apachesolr_query_alter($query) rather than re-writing the search path.

Am I correct this is the sticking point others have had? Are there better methods for altering apachesolr_search_custom_page_search_form and having apachesolr use the new form values?