Implement like operator for search_api_db

Created on 26 April 2023, over 1 year ago
Updated 3 February 2024, 11 months ago

Make it possible to use search_api_db as a drop-in replacement for filters in views.

Background: I have about 750K entries in a node bundle without about 20 fields defined on it. This makes it slow to even just display an overview with paging active, since Drupal generates a gigantic query to get at the data. When I replace the view by a search_api based view the output is generated much quicker when it comes from the indexes. However text filters in that search_api based view are not behaving as they would be in regular views, especially concerning partial searches.
So, request: find a solution to make search_api_db filters work as the regular (contains) filter.

What I'm trying to use it for:
- I have dossiers in Drupal that have titles like "D-2022-0000001813", "D-2022-0000021813", "D-2022-0000001814".
- I want to be able to filter title on e.g. "01813", then in the above 3 examples I only expect the first one to be returned (which it does with the regular "contains" filter).
- Depending on the option I take in search_api I get 2 results:
a) I can search/filter on the full title, but when I filter on a partial title nothing is returned (with string) or
b) full text: even with no processors active (in the config screen) my titles get tokenized in e.g. "2022 and 1813", "2022 and 21813", ... And when I search e.g. on 01813 I get returned both "D-2022-0000001813" and "D-2022-0000021813" since it strips away the 0

I experimented a bit to show what I would need more or less:

function mymodule_search_api_query_alter(\Drupal\search_api\Query\QueryInterface &$query) {
  foreach ($query?->getConditionGroup()?->getConditions()[0]?->getConditions() as $key => $condition) {
    $value = $condition?->getValue();
    if (!empty($value) && is_string($value)) {
      $operator = $condition?->getOperator();
      if ($operator === '=') {
        $condition->setOperator('LIKE');
        $condition->setValue('%' . $value . '%');
      }
    }
  }
}

And then a patch like the following to add the LIKE operator:

diff --git a/src/Backend/BackendPluginBase.php b/src/Backend/BackendPluginBase.php
index bf4b575..c929f2f 100644
--- a/src/Backend/BackendPluginBase.php
+++ b/src/Backend/BackendPluginBase.php
@@ -324,6 +324,7 @@ abstract class BackendPluginBase extends ConfigurablePluginBase implements Backe
       case 'NOT IN':
       case 'BETWEEN':
       case 'NOT BETWEEN':
+      case 'LIKE':
         return;
     }
     throw new SearchApiException("Unknown operator '$operator' used in search query condition");

After this the fields I target work to filter partially... but of course the above is a very dirty hack just for testing, overwriting the '=' functionality.

So in short I would like search_api_db to support the contains/like operator (on string), and make it configurable through search_api views integration.

Regards,
Sven

Feature request
Status

Active

Version

1.29

Component

Views integration

Created by

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

Comments & Activities

  • Issue created by @sboden
  • 🇦🇹Austria drunken monkey Vienna, Austria

    Thanks for suggesting this improvement!

    Amazingly, there indeed doesn’t seem to be an issue for this yet. At least, none that I could find. So, thanks for opening it.

    Seems like the actual functionality could indeed be added very easily. The parts that are more work would be …

    1. to make the implementation generic enough to make sure we do not break sites using other search backends. This would be done by defining a new backend feature for the functionality – in this case, accepting the LIKE (and, maybe, NOT LIKE?) operator(s). And
    2. to add test coverage making sure this works as expected.

    As I currently don’t really have time to work on feature requests, except for reviewing and similar help, this would depend on you (or someone else) providing an initial patch for this, adding not only the functionality but also defining the feature and containing test coverage.

  • In the meantime I worked around it, but I will probably need the functionality later on. I can give it try.
    Any preference for the name of the (new) backend feature?

  • 🇦🇹Austria drunken monkey Vienna, Austria

    Thanks, sounds good! Please just ask if you need any further pointers.
    I think search_api_like_op would be a good name, and should probably already cover NOT LIKE as well.

  • 🇦🇹Austria drunken monkey Vienna, Austria

    See Support LIKE and NOT LIKE operators in database backend Needs review for a first step for this: just supporting the new operators internally, without exposing them in the UI.

Production build 0.71.5 2024