"is one of" operator is ignored for a view's exposed filter

Created on 7 February 2023, about 2 years ago
Updated 10 August 2023, over 1 year ago

Setup

  • Solr version: 8.11.2
  • Drupal Core version: 10.0.3
  • Search API version: 8.x-1.28
  • Search API Solr version: 4.2.10
  • Configured Solr Connector: Standard
  • solrconfig_extra.xml is modified as follow in order to set the operator "AND" as default for query expressions:

    <requestHandler name="/select" class="solr.SearchHandler">
      <lst name="defaults">
        <str name="defType">lucene</str>
    ...
        <str name="q.op">AND</str>
      </lst>
    ...
    </requestHandler>
    

Steps to reproduce:

  • Create an index named "my_solr_index" for a Solr instance named "my_solr_core", choose "Content" as datasources
  • Add a field for an existing taxonomy vocabulary to the index, let the type "integer" by default, give it the name "test_id"
  • Create a view with a rest export display for this index
  • Add an exposed filter for the field added previously in the index, choose the selection type "dropdown", set by default the operator "is one of" and give the ID "test" for this filter, expose the operator and give it the name "op_test"
  • Set a path for this display

Issue

I don't know if it is an issue related to Search API or to the module Search API Solr, sorry if the issue was already posted.

When accessing the rest export path and writing manually the query string, it works (e.g. we've got the results we're looking for) if we set only an existing taxononomy term ID in the query, ex:

/rest_export_path?test[]=10

But it fails (e.g. no result) if we set several taxonomy term IDs in the query, ex:

/rest_export_path?test[]=10&test[]=13

It works only for the nodes where these two taxononomy terms are referenced.

We've got results (but not those we are looking for) if we set manually the operator to "not":

/rest_export_path?test[]=10&test[]=13&op_test=not

But no result with the operator "or" which should be set by default by the way:

/rest_export_path?test[]=10&test[]=13&op_test=or

When looking to the Solr server logs, we see this kind of line:

2023-02-07 16:52:54.849 INFO (qtp1642785848-98) [ x:my_solr_core] o.a.s.c.S.Request [my_solr_core] webapp=/solr path=/select params={hl=true&TZ=Europe/Paris&fl=ss_search_api_id,ss_search_api_language,score,hash&hl.requireFieldMatch=false&hl.fragsize=0&fq=itm_test_id:("10"+"13")&fq=%2Bindex_id:my_solr_index&fq=ss_search_api_language:"fr"&hl.simple.pre=[HIGHLIGHT]&hl.mergeContiguous=false&wt=json&json.nl=flat&start=0&rows=12&hl.snippets=3&q=*:*&hl.simple.post=[/HIGHLIGHT]&omitHeader=true} hits=0 status=0 QTime=0

We see that the query for the taxonomy term IDs is wrongly set for the "and" operator :

fq=itm_test_id:("10"+"13")

It should be set like this:

fq=itm_test_id:(10 13)

Or like this :

fq=itm_test_id:("10" OR "13")

It works (e.g. we've got the results we are looking for) if we set the query manually from the Solr server UI.

I tried to use the hook_views_query_alter or hook_search_api_query_alter but I can't figured out how to change the conjecture for the group conditions related to the field.

πŸ’¬ Support request
Status

Fixed

Version

4.2

Component

Code

Created by

πŸ‡«πŸ‡·France gaspounet

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @gaspounet
  • πŸ‡«πŸ‡·France gaspounet

    By digging a little more it turns out that the problem comes in fact from the quotation marks used in the query

    fq=itm_test_id:("10"+"13") <== NOT WORKING

    fq=itm_test_id:(10+13) <== OK !

    Is there a way to check that the value is numeric and in this case treat it as such ?

  • πŸ‡«πŸ‡·France gaspounet

    Well me, it's nice talking to myself
    A credit to dementia

    β€”Megadeth, Sweating Bullets

    OK so the problem was coming from the modification I made in my solrconfig_extra.xml file:

    <requestHandler name="/select" class="solr.SearchHandler">
      <lst name="defaults">
        <str name="defType">lucene</str>
    ...
        <str name="q.op">AND</str>
      </lst>
    ...
    </requestHandler>

    If I remove the "q.op" parameter to let the operator by default for query expressions (operator "OR"), it is working as expected...

    In the first place I set this parameter to "AND" to suit my needs for my fulltext filters: I want only results were we can find all the words in the search phrases typed by the user without the user having to separate them manually with the keywords "AND" or "&&" which is not working for my views where I use the direct parsing mode which ignores the operator "contains all words".

  • πŸ‡«πŸ‡·France gaspounet

    And so, in order to obtain the results I'm looking for using taxonomy IDs exposed filters alongside fulltext fields using the direct parse mode and the "contains all words" operator, I need to rewrite the query thanks to a hook function:

    function MYMODULE_views_query_alter( $view, $query ) {
      switch( $view -> id() ) {
        case 'my_solr_index_view':
          //Get the fulltext search value when using direct parse mode
          $cleanKeys = " " . $query -> getKeys();
          //remove all quotes if there is an odd number of quotes
          if ( substr_count( $cleanKeys, '"' ) % 2 !== 0 ) {
            $cleanKeys = str_replace( "\"", " ", $cleanKeys );
          }
          //Remove all parentheses if the number of open parentheses does not match the number of closed parentheses
          if ( substr_count( $cleanKeys, '(' ) != substr_count( $cleanKeys, ')' ) ) {
            $cleanKeys = str_replace( "(", " ", $cleanKeys );
            $cleanKeys = str_replace( ")", " ", $cleanKeys );
          }
          //Clean operator keywords
          $cleanKeys = str_replace( "+", " AND ", $cleanKeys );
          $cleanKeys = str_replace( "&&", " AND ", $cleanKeys );
          $cleanKeys = str_replace( "||", " OR ", $cleanKeys );
          $cleanKeys = str_replace( "\"", " \" ", $cleanKeys );
          $cleanKeys = str_replace( " -", " NOT ", $cleanKeys );
          $cleanKeys = trim( preg_replace( '/\s+/', ' ', $cleanKeys ) );
          $cleanKeys = preg_replace( "/^(AND |OR |NOT )/", "* $1", $cleanKeys );
          //Loop through the query in order to add the "AND" operator between words when the operator is not explicitly written and when we are not looking for exact match
          $solrBooleans = [ "AND", "OR", "NOT" ];
          $newKeys = [];
          $previousKey = "";
          $exactWord = false;
          foreach ( explode( " ", $cleanKeys ) as $key ) {
            if ( $key == "\"" ) {
              $exactWord = !$exactWord;
              $newKeys[] = $key;
            } else {
              if ( $exactWord || !$previousKey || in_array( $key, $solrBooleans ) || in_array( $previousKey, $solrBooleans ) ) {
                $newKeys[] = $key;
              } else {
                $newKeys[] = "AND";
                $newKeys[] = $key;
              }
            }
            $previousKey = $key;
          }
          $query -> keys( implode( " ", $newKeys ) );
        break;
      }
    }
    

    Please let me know if there is a better way (sure there is!).

  • πŸ‡©πŸ‡ͺGermany mkalkbrenner πŸ‡©πŸ‡ͺ

    The problem is that you manipulated the default operator and set it to AND.
    The internal query builder of the module doesn't know that and builds all queries and filter queries for a OR as default operator.
    Setting it to AND is not supported by this module. But "contains all" should build the correct query.

  • Status changed to Fixed over 1 year ago
  • πŸ‡©πŸ‡ͺGermany mkalkbrenner πŸ‡©πŸ‡ͺ
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024