Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get and order the most relevant entries from the database with multiple keywords Laravel 5

I am having trouble handling multiple keywords and querying the database based on relevance. I want to search each row and if there is more than 1 keyword per row matching based on my selected columns, to sort these entries first.

I do have something working, but it just pulls all entries with a keyword present in a column in no specific order or relevance.

Take this working example:

$search_terms = array('York', 'North Yorkshire');

$properties = Property::where(function ($q) use ($search_terms) {
            foreach ($search_terms as $value) {
                $q->orWhere('address1', 'like', "%{$value}%");
                $q->orWhere('address2', 'like', "%{$value}%");
                $q->orWhere('postcode', 'like', "%{$value}%");
                $q->orWhere('city_town', 'like', "%{$value}%");
                $q->orWhere('county', 'like', "%{$value}%");
            }
        })->paginate(25);

This works and pulls back all entries with the keywords present in any of my selected columns. In this instance York from the city_town column and North Yorkshire from the county column.

I need the the query to check each individual row for these keywords and bring back entries where ALL of these keywords are present, followed by where one or more is present afterwards (my example does this now).

Many thanks in advance to anyone who can help.

like image 271
Nick Howarth Avatar asked Sep 19 '25 15:09

Nick Howarth


1 Answers

Okay maybe some SQL magician could give you a better SQL solution. But until then...

This is how I would do it with Laravel collections (sorting with php):

$search_terms = array('York', 'North Yorkshire');

$properties = Property::where(function ($q) use ($search_terms) {
            foreach ($search_terms as $value) {
                $q->orWhere('address1', 'like', "%{$value}%");
                $q->orWhere('address2', 'like', "%{$value}%");
                $q->orWhere('postcode', 'like', "%{$value}%");
                $q->orWhere('city_town', 'like', "%{$value}%");
                $q->orWhere('county', 'like', "%{$value}%");
            }
        })->paginate(25);

$props = ['address1', 'address2', 'postcode', 'city_town', 'county'];

$properties = $properties->sortByDesc(function($i, $k) use ($search_terms, $props) {
    // The bigger the weight, the higher the record
    $weight = 0;
    // Iterate through search terms
    foreach($search_terms as $searchTerm) {
        // Iterate through properties (address1, address2...)
        foreach($props as $prop) { 
            // Use strpos instead of %value% (cause php)
            if(strpos($i->{$prop}, $searchTerm) !== false)
                $weight += 1; // Increase weight if the search term is found
        }
    }

    return $weight;
});

$properties = $properties->values()->all();
like image 56
DevK Avatar answered Sep 22 '25 08:09

DevK



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!