Search returns unexpected results

Hi!

I am building a search function for a website and created a route, that returns a fully built html table with the results which is then fetched as soon as the user is typing into the search field. It works almost as expected, but of course I cannot use regular spaces in the search string, as it needs to work as a URL for the route. I then replaced every space in the input string with “%space%” and used str_replace in the route to change it back to a space.

However now whenever I search and use a space it results in posts that contain any one of the words when I expected it to only show when all words fit the post. So it adds other projects as soon as I use a space. As if they were separate search terms.

Example with only one word only shows one project:

Example with two words shows two projects

For the search I of course need a different behaviour. How can I achieve that it only shows projects that contain all of the separate words that were typed?

This is what my route looks like:

      [
        'pattern' => '/search/(:any)',
        'action'  => function ($any) use ($kirby) {

          $searchTerm = str_replace('%space%', ' ', $any);
          $results = $kirby->site()->search($searchTerm, 'title|name', ['words' => true]);

          $html = "<table class='index-table search-results-table'>";
          $html .= "<thead><tr><th>Name</th><th>Titel</th></tr></thead>";

          $arr = [];
          foreach($results as $result) {
            $html .= "<tr><th>" . $result->name() . "</th><th>" . $result->title() . "</th></tr>";
          }

          $html .= "</table>";
          return $html;
        }
      ]

and on the frontend:

searchField.addEventListener('input', (input) => {
  (async () => {
    const results = await fetchSearchResults(searchField);
    searchContainer.innerHTML = results;
  })()

});

async function fetchSearchResults(searchField) {
  const searchTerm = searchField.value;
  const cleanSearchTerm = searchTerm.replace(' ', "%space%");
  const response = await fetch(`/search/${cleanSearchTerm}`);
  const searchResults = await response.text();
  return searchResults;
}
1 Like

Kirby’s built-in search doesn’t support AND logic for search terms. You would have to write your own custom search component.

There’s also a search plugin but I’m not sure if it supports AND or not.

1 Like

There’s also this one:

2 Likes

Thank you texnixe! Bettersearch was easy to implement and works as expected with two words but somehow stops working for me when I type a third word. I will check out the other plugin tomorrow and will report back. It appears to have the option of the AND operator.

Update: Bettersearch works perfectly fine. I did the mistake of using the js function .replace instead of .replaceAll and so it only replaced the first space.

async function fetchSearchResults(searchField) {
  const searchTerm = searchField.value;
  const cleanSearchTerm = searchTerm.replaceAll(' ', "%space%");
  const response = await fetch(`/search/${cleanSearchTerm}`);
  const searchResults = await response.text();
  return searchResults;
}