For a client's site, I have a View which displays nodes which contain an Addressfield, and I have exposed filters on the View for most fields, including that Addressfield. The client noticed that, when they tried to filter by locations in Oregon, all locations around the country were shown, but filtering worked as expected for every other state. After some experimentation and with the help of someone going by "elyograg" in #solr, I found that it had to do with the fact that we were using "OR" to identify Oregon was throwing Solr off, as it's a reserved word for binary searching (eg, "foo OR bar"). I found similar results using "Not" in a text field on the same View/form. (Oddly, everything works as expected on my local dev machine, but fails as described on the Acquia-hosted staging site. elyograg thinks it has something to do with a different query parser being used on my machine.)

I suppose there might be a few ways to fix this, in rough order of complexity:

  1. Add a Search API processor which escapes special characters and keywords (here's a list) for all queries to that index (or possibly just escapes the whole query). Applying this will make these sorts of operators unable to be used on any queries to the index; in some cases it may be good enough, but I suspect in many it'll be too brute force.
  2. Add an option to exposed filter settings forms to escape its submitted value when building the query. (I'm not sure that there's an elegant way to add options to all exposed filter configuration forms, though… Might be wrong, but I seem to remember not being able to do something like that elegantly in the past.)
  3. Just go ahead and automatically escape the query in contexts where we don't expect the user to be using boolean operators anyway, such as pre-defined items in select fields (as was the case with Oregon above).
  4. Perhaps some combination of the two above.

I'm willing to help develop this, but figured I'd solicit feedback first on which route we should take.

Comments

drunken monkey’s picture

What type has the Adressfield in the index? String or fulltext?
Normally, conditions will always be escaped in Solr just for that reason. You need to use very specific configuration, as far as I'm aware, to allow the user to use Solr operators.
Could you maybe try to debug the Solr query and post the Solr request and response here?

Garrett Albright’s picture

Unfortunately, as this is only happening on Acquia's server (I can't replicate it locally) where I don't have access to the Solr logs, I cannot debug it, no. :( I still haven't found a solution, though, even after going back and forth with Acquia's support. After all the time spent trying to get it to work "properly," the solution I'm going to try to implement next is to change Oregon's abbreviation from "OR" to "OE" or something. I'm giving up on this one. :(

drunken monkey’s picture

Project: Search API Solr » Acquia Search for Search API
Version: 7.x-1.6 » 7.x-2.x-dev
Category: Feature request » Support request

Hm, then maybe the problem is in the Acquia service class?

@ Nick: Is it possible you are somewhere changing the fq parameters that are built to allow an unquoted value to come through? I just tested, and with normal Search API Solr Search all condition values are always in quotes.

drunken monkey’s picture

See also #2333133-8: No results returned when filtering by multi-word value – do you maybe already have something similar in the Acquia service class?

Garrett Albright’s picture

For the record, I ended up working around this by changing everything - Migrate scripts, Addressfield, etc - to store/search for Oregon as "ORE" instead of "OR." A stupid workaround, but at least it works. =/

hoang027’s picture

Running into the similar problem with a Solr facet on my "sm_field_state" index. Basically this is a List(text) field, with enumerated values:

AL|Alabama
AK|Alaska
AZ|Arizona
...
OR|Oregon
...

Since I'm racing against our deadline, what I did was to modify our apachesolr_query_alter() hook and add the quote just for that field:

if ($query->hasFilter('sm_field_state', 'OR')) {
$query->removeFilter('sm_field_state', 'OR');
$query->addFilter('sm_field_state', '"OR"');
}

This bug is relatively easy to reproduce, looking forward to having it fixed properly (ahem, drunken monkey, master of search :-) Thanks.

hoang027’s picture

My previous temporary fix with query_alter() didn't work when the facet's operator is OR. After some debugging, found out that the field values are only quoted if they contain whitespace or special chars, and only if the operator is "OR". I'm wondering why they're not always quoted like drunken monkey mentioned in #3. Anyway, I modified the function execute() in apachesolr/plugins/facetapi/query_type_term.inc to always quote the values:

    // Adds filter based on the operator.
    if (FACETAPI_OPERATOR_OR != $operator) {
      foreach ($active as $value => $item) {
        // Handle facet missing:
        if ($value === '_empty_' && !empty($settings->settings['facet_missing'])) {
          $query->addFilter($this->facet['field'], '[* TO *]', TRUE);
        }
        elseif (strlen($value)) {
          $query->addFilter($this->facet['field'], '"'.$value.'"');
        }
      }
    }
    else {
      // OR facet.
      $local = "tag={$this->facet['field']}";
      $values = array_keys($active);
      if ($values) {
        $query->addFilter($this->facet['field'], '("' . implode('" OR "', $values) . '")', FALSE, $local);
      }
    }

Maybe drunken monkey can review the above modification and commit a fix?

EDIT: diff included below, against apachesolr version 1449085462

diff --git a/sites/all/modules/apachesolr/plugins/facetapi/query_type_term.inc b/sites/all/modules/apachesolr/plugins/facetapi/query_type_term.inc
index 03f7aa3..f99edad 100644
--- a/sites/all/modules/apachesolr/plugins/facetapi/query_type_term.inc
+++ b/sites/all/modules/apachesolr/plugins/facetapi/query_type_term.inc
@@ -56,7 +56,7 @@ class ApacheSolrFacetapiTerm extends FacetapiQueryType implements FacetapiQueryT
           $query->addFilter($this->facet['field'], '[* TO *]', TRUE);
         }
         elseif (strlen($value)) {
-          $query->addFilter($this->facet['field'], $value);
+          $query->addFilter($this->facet['field'], '"'.$value.'"');
         }
       }
     }
@@ -65,13 +65,7 @@ class ApacheSolrFacetapiTerm extends FacetapiQueryType implements FacetapiQueryT
       $local = "tag={$this->facet['field']}";
       $values = array_keys($active);
       if ($values) {
-        // Quote any values that have white space or colons.
-        foreach ($values as &$v) {
-          if (preg_match('/[:\s]/', $v) || strlen($v) == 0) {
-            $v = '"' . $v . '"';
-          }
-        }
-        $query->addFilter($this->facet['field'], '(' . implode(' OR ', $values) . ')', FALSE, $local);
+        $query->addFilter($this->facet['field'], '("' . implode('" OR "', $values) . '")', FALSE, $local);
       }
     }
   }
janusman’s picture

Status: Active » Closed (works as designed)

While this could have to do either with the Solr backend or with the Search API Solr module... it certainly can't be due to Search API Acquia (because it is only a connector module, and does not alter queries in any way).

So, you could ask for help via an Acquia Support ticket if you suspect the backend... or if it's the Search API Solr module, then we can change the issue back to point to that project.

In any case, I'm closing this for now.