Hi,

I'm using Search API with Views and when I search for word1 word2 my query becomes "word1" "word2"

This is because SearchApiSolrService::flattenKeys call SearchApiSolrConnection::phrase for each element of $keys.
Is it really needed? Because of that I can't search for word* because the query is transformed to "word*" and the wildcard character is interpreted as a whitespace character by Solr.

Is there any way to really search word*?

Comments

Claire Hernandez’s picture

I am too really interested by the answer to this question. Dear mainteners, does a patch with what Julian said would help and would be integrated ?

_wdm_’s picture

StatusFileSize
new480 bytes

It looks like the wrong escaping method has been used, the attached patch swaps SearchApiSolrConnectionInterface::phrase for SearchApiSolrConnectionInterface::escapePhrase.

This looks like a new option is required to let the config pick the escaping method.

drunken monkey’s picture

Just use the "Direct query" parse mode (in the page settings, or in Views under Advanced > Query settings) if you want to use Solr's query syntax. Otherwise, entered words will always be searched as they are entered (except quotes).

kenorb’s picture

drunken monkey’s picture

Category: bug » support
Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

lex0r’s picture

Issue summary: View changes
Status: Closed (fixed) » Active

I tried to use direct query mode, but it doesn't affect anything - the keys are anyway passed through flattenKeys and ::phrase. The only place where direct mode is used is here:

search_api/includes/query.inc:

protected function parseKeys($keys, $mode) {
    if ($keys === NULL || is_array($keys)) {
      return $keys;
    }
    $keys = '' . $keys;
    switch ($mode) {
      case 'direct':
        return $keys;
...
}

Although keys are returned as is, no more direct mode checks are made further in the call stack to consider this, and keys are just escaped using "phrase" method.

So, the following code will not work even in direct mode:

// $search is instance of SearchApiQuery.
$search->keys("wildca*");
$search->execute();
// Will result in Solr query like this:
// q=wildca
// while q=wildca* is expected.

If all the above is not just my misunderstanding this is not a support request but a bug.

lex0r’s picture

Category: Support request » Bug report
StatusFileSize
new1.43 KB

I'm actually inclined to think this is a bug, since search_api_solr which is in charge of sending server-specific request just ignores the parse mode. Please see the patch and let me know if all this discussion does make any sense :)

kenorb’s picture

Status: Active » Needs review
drunken monkey’s picture

Category: Bug report » Support request
Status: Needs review » Active

Although keys are returned as is, no more direct mode checks are made further in the call stack to consider this, and keys are just escaped using "phrase" method.

The "parse mode" is not made to be followed by the backend plugins, it's just there for the query to parse the keys. The way the query "signals" to the backend whether it should take the keywords as-is or pre-process them (i.e., use flattenKeys() and phrase(), in the case of Solr) is by letting the keywords be a string or an array. In the former case, they should be handed unprocessed to the search engine (if possible), in the latter case they should be escaped.
And, if you look at the Solr backend plugin, you'll see that we do check for is_array($keys) before calling flattenKeys(). This is definitely working correctly.

It seems there is some complication on your system for this, maybe something else altering the keys, or adding their own.
To test, use something like the following:

  $query = $index->query(array('parse mode' => 'direct'))
    ->fields(array('body:value'))
    ->keys('wildca*');
  $response = $index->server()->search($query);

This will circumvent any preprocessing that might otherwise occur.

lex0r’s picture

StatusFileSize
new1.82 KB

The "parse mode" is not made to be followed by the backend plugins, it's just there for the query to parse the keys.

However, it is backend that parses the query, not only the query class:

    // Formatting the keys into a Solr query can be a bit complex. The following
    ...
       // If there was just a single, unnested key, we can ignore all this.
    if (count($k) == 1 && empty($nested_expressions)) {
      $k = reset($k);
      return $neg ? "*:* AND -$k" : $k;
    }

    if ($or) {
      if ($neg) {
        return '*:* AND -' . implode(' AND -', $k);
      }
      return '((' . implode(') OR (', $k) . '))';
    }
    $k = implode(' AND ', $k);
    return $neg ? "*:* AND -($k)" : $k;

What is the code above if not original query parsing into a string having Solr query syntax?

For those who still want to have AND/OR handled by backend class, and use keys in array form, check the updated #8 patch with a bug fix attached.

kenorb’s picture

Status: Active » Needs review
drunken monkey’s picture

Status: Needs review » Fixed

What is the code above if not original query parsing into a string having Solr query syntax?

That's not parsing, since it's already receiving a structured array of keywords. "Formatting" maybe.
But that's semantics – my point that the parse mode is only for the query still stands.

But sure, if someone wants it differently, they can just use your patch.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.