How to use search to include multiple "words"

Hello again @texnixe! With Kirby 3 around the corner I’m curious if a revised search has made it in. Let me know, thanks!

I have the same problem with Kirby 3.

While I could modify the source code at /kirby/src/Cms/Search.php#L43 and change it to $searchwords = array($searchwords), I wonder if there’s a more future-proof way.
Can I somehow overwrite the core function like @lukasbestle did for Kirby 2?

To be honest I am wondering why the “each word separately” approach is used at all. It’s not what users expect and it’s more performance-intensive.

@thguenther, I am currently porting an existing project to K3 and I have reused this succesfully:

// site/plugins/mysearch/index.php
/**
* Fork of the native $pages->search() method
* Only searches for full matches
*/
function search($collection, $query, $params = array()) {

    if(is_string($params)) {
        $params = array('fields' => str::split($params, '|'));
    }

    $defaults = array(
        'minlength' => 2,
        'fields'    => array(),
        'words'     => false,
        'score'     => array()
    );

    $options = array_merge($defaults, $params);

    if(empty($query)) return $collection->limit(0);

    $results = $collection->filter(function($page) use($query, $options) {
        $data = $page->content()->toArray();
        $keys = array_keys($data);

        if(!empty($options['fields'])) {
            $keys = array_intersect($keys, $options['fields']);
        }

        $page->searchHits  = 0;
        $page->searchScore = 0;

        foreach($keys as $key) {
            $score = a::get($options['score'], $key, 1);

            // check for full matches
            if($matches = preg_match_all('!' . preg_quote($query) . '!i', $data[$key], $r)) {
                $page->searchHits  += $matches;
                $page->searchScore += $matches * $score;
            }
        }

        return $page->searchHits > 0 ? true : false;
    });

    $results = $results->sortBy('searchScore', SORT_DESC);

    return $results;
}

It’s not a $pages-method, but afaik does the job as separate search($pages, $query, $options) function. If you’ld like you could easily turn it into one via plugin options…

3 Likes

Thanks a lot, @bvdputte :heart:

Thank You for Your solution for Kirby 3!
Could not figure out what I should adjust to search for exact multiple words (not each individual word) for entire $site and not $page.

Currently using (default) search this way: $searchResults = $site->index()->listed()->search('some search input');

Hey @Bristolscript ,

The code above has no $pages method, which might be confusing.

With the code above, you should be able to use it as follows:
$searchResults = search($site->index()->listed(), 'some search input');

Thank You! It’s working. Previously forgot to add in plugin index.php file: <?php

Is it possible to do that within Kirby 3.9 now without a plugin?