I try to query Apache Solr to generate some search results.

$results = apachesolr_search_execute('some keywords','tid:1','','my/base/path',0,'mymodule');

this works perfectly well. The problems arise when i try to do this:

$results = apachesolr_search_execute('some keywords','tid:1 (tid:2 OR tid:3)','','my/base/path',0,'mymodule');

Somewhere I probably missed something, but to me, this should mean: give me all the nodes matching:

  • some keywords
  • assigned to term with tid = 1
  • assigned to term with tid = 2 or assigned to term with tid = 3

It doesn't work like this. My question is: how does it work? It it possible to query solr with this? And if yes: how?

Thanks in advance for your help.

Comments

jersu’s picture

I'm trying to solve something similar, I thought this would work, but does not, nor does char encoding the plus (&43;)

$results = apachesolr_search_execute('some keywords','tid:1 tid:[2+OR+3]','','my/base/path',0,'mymodule');
jersu’s picture

After some more digging, found that solr is capable of searching with a param like fq=(tid:2+OR+tid:3), but at present, the Solr_Base_Query class doesn't like a filter passed in like that. It only allows range queries through, otherwise it wraps it in quotes. It also wants to set the filter like name:value, but we want to set it like (name:value+OR+name:value) ... a solution that would require some extra work.

From the Solr_Base_Query (in the apachesolr mod directory)

  /**
   * Takes an array $field and combines the #name and #value in a way
   * suitable for use in a Solr query.
   */
  public function make_filter(array $filter) {
    // If the field value has spaces, or : in it, wrap it in double quotes.
    // unless it is a range query.
    if (preg_match('/[ :]/', $filter['#value']) && !isset($filter['#start']) && !preg_match('/[\[\{]\S+ TO \S+[\]\}]/', $filter['#value'])) {
      $filter['#value'] = '"'. $filter['#value']. '"';
    }
    $prefix = empty($filter['#exclude']) ? '' : '-';
    return $prefix . $filter['#name'] . ':' . $filter['#value'];
  }
pwolanin’s picture

See the apachesolr_nodeacess module under the contrib/ dir for its construction of an OR fq parameter.

$query->add_subquery($subquery, 'OR');

---
Work: BioRAFT

joetsuihk’s picture

It seems it makes the query tid:1 OR tid:2

But how to implement tid:3 (tid:1 OR tid:2)?

These do not work:

  $query1 = apachesolr_drupal_query();
  $query1->add_filter("tid", 20);

  $query2 = apachesolr_drupal_query();
  $query2->add_filter("tid", 21);

  $query1->add_subquery($query2, 'OR');

  $query->add_subquery($query1, 'AND');
johnnybgoode’s picture

To OR join two filters, what you want to do is:

function my_module_modify_query(&$query, &$params, $caller) {
  // Remove any filters that should be OR joined from the primary query.
  $query->remove_filter('my_filter', 'my value');
  
  // Create subquery with all filters to OR join.
  $query2 = apachesolr_drupal_query();
  $query2->add_filter('my_filter', 'my_value');
  $query2->add_filter('my_filter', 'my_value_2');

  /* Add subquery to main query.
   *
   * add_subquery arg2 OR joins the filters
   * add_subquery arg3 AND joins the subquery to the primary query
   */
  $query->add_subquery($query2, 'OR', 'AND');
}
torgospizza’s picture

Thanks for this, it was helpful - although in D7 now you use the SolrFilterSubQuery class and $query->addFilterSubQuery to attach them to your query, but the method was otherwise identical.

Have I helped you? Consider buying me a beer.

ardnet’s picture

And how to make range filter say like from 1000 to 2000 for example? I gotta hard time how to do this.

ardnet’s picture

nvrmind, got it

$query->add_filter("tps_salary", "[1000 TO 2000]");