Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use multiple filters to widen the search in Apachesolr queries

Making a search with Apachesolr, i want to add a couple of filters in hook_apachesolr_prepare_query(&$query). This works fine, except I want the filters to widen the search ('OR'), rather than narrow it ('AND').

For example, if I have 4 nodes of type:A and 3 of type:B that match a search, to filter by type:A and type:B should return 7 nodes (of type:A AND nodes of type:B), rather than 0 those of type:A which are also of type:B.

I saw a suggestion to do this using the model of nodeaccess

foreach ($filters as $filter) {
  $subquery = apachesolr_drupal_query();
  if (!empty($subquery)) {
    $subquery->add_filter('type', $filter);
    $query->add_subquery($subquery);
  }
}

but this doesn't seem to work. (It doesn't return any results).

I then tried (as I have a limited number of node types) excluding the types that I don't want:

$excludes = array('A', 'B', 'C');
$excludes = array_diff($excludes, $filters);
$exclude = implode('&', $excludes);
$query->add_filter('type', $exclude, TRUE);

This method of stitching them together doesn't work (the '&' gets escaped) but neither does adding them as subqueries, similar to the manner above.

Any suggestions on how to do this?

like image 502
lazysoundsystem Avatar asked Aug 24 '10 15:08

lazysoundsystem


1 Answers

With Drupal7 and the last apacheSolr API, you can do OR filters by doing this :

function my_module_apachesolr_query_alter($query) {
  // first, create a subQuery filter to store others
  // and specify there is a "OR" condition
  $filter = new SolrFilterSubQuery('OR');

  // next, add all filters on bundle you want, each as
  // a new subQuery filter, always with "OR" condition
  // and add it to the primary filter
  $a = new SolrFilterSubQuery('OR');
  $a->addFilter('bundle', 'A');
  $filter->addFilterSubQuery( $a );

  $b = new SolrFilterSubQuery('OR');
  $b->addFilter('bundle', 'B');
  $filter->addFilterSubQuery( $b );

  $c = new SolrFilterSubQuery('OR');
  $c->addFilter('bundle', 'C');
  $filter->addFilterSubQuery( $c );

  // finally, add the primary subQuery filter as
  // subquery of the current query 
  $query->addFilterSubQuery( $filter );

}

And your query search about type A OR type B OR type C (all results in each types). You can combine OR / AND by changing the parameter of the SolrFilterSubQuery instanciation.

Special thanks to this page and it's author : http://fr.ench.info/blog/2012/04/03/Add-Filters-ApacheSOLR.html

like image 107
titouille Avatar answered Oct 07 '22 15:10

titouille