Currently I have a simple search engine on my site
I’m trying to match the keyword
in all fields.
Here’s the simplified working codes
$keyword_search = "Hello World"; $delimeter = ' '; //or your separator $keywords = explode($delimeter, $keyword_search); $base_query = AppModelsEntireSearchSite::where('id','!=',NULL); foreach($keywords as $keyword){ $base_query->where(function($query) use ($keyword){ $query->where('part_number', 'like', '%' . $keyword . '%') ->orWhere('part_name', 'like', '%' . $keyword . '%') ->orWhere('category', 'like', '%' . $keyword . '%') ->orWhere('description', 'like', '%' . $keyword . '%'); }); } $data = $base_query->paginate(20); return $data;
What I’m trying to do is to match all keyword, count all matched keyword (for every occurences) and do Order By Desc
from highest occurences to lowest.
If I enter "Hello World"
it will find all the data that will match to "Hello World"
I got part_number, part_name, category, description
fields
it will sum the total number of occurrences on all fields and arrange the ORDER BY
from highest to lowest (DESC)
EXAMPLE:
DATA #1
number of matched keyword in part_number
is 0
number of matched keyword in part_name
is 2
number of matched keyword in category
is 0
number of matched keyword in description
is 0
TOTAL = 2
DATA #2
number of matched keyword in part_number
is 0
number of matched keyword in part_name
is 0
number of matched keyword in category
is 2
number of matched keyword in description
is 10
TOTAL = 12
DATA #3
number of matched keyword in part_number
is 0
number of matched keyword in part_name
is 0
number of matched keyword in category
is 0
number of matched keyword in description
is 5
TOTAL = 5
and order by desc should be something like this
DATA#2
DATA#3
DATA#1
UPDATE*
Tried the answer from @Anas
$delimeter = ' '; //or your separator $keywords = explode($delimeter, $keyword_search); $base_query = AppModelsEntireSearchSite::where('id','!=',NULL); foreach($keywords as $keyword){ $base_query->where(function($query) use ($keyword){ $query->where('part_number', 'like', '%' . $keyword . '%') ->orWhere('part_name', 'like', '%' . $keyword . '%') ->orWhere('category', 'like', '%' . $keyword . '%') ->orWhere('description', 'like', '%' . $keyword . '%'); }); } foreach($keywords as $keyword){ $base_query->selectRaw(function($querySelect) use ($keyword){ $querySelect->selectRaw(' Round ((Char_length(Concat( part_number, part_name, category, description )) - Char_length(REPLACE ( Concat( part_number, part_name, category, description ), "'.$keyword.'", ""))) / Char_length("'.$keyword.'")) AS count '); }); } $data = $base_query->orderBy('count','DESC')->paginate(20); return $data;
But I’m getting undefined column count
Update
Applied answer by @Donkarnash
Advertisement
Answer
Try to concat related column in one string then get total number of occurrences by this query sample. also you can use in select DB:raw() Laravel Documentation
SELECT email, name, Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "anas", ""))) / Char_length("anas")) AS count FROM users Having count >0 ORDER BY count DESC;
Result of query
For sperate Keyword you can sum new Round function with different keyword check this query
SELECT email, name, Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "first_keyword", ""))) / Char_length("first_keyword")) + Round ((Char_length(Concat(email, name)) - Char_length(REPLACE ( Concat(email,name), "second_keyword", ""))) / Char_length("second_keyword")) AS count FROM users Having count >0 ORDER BY count DESC;
To make it case insensitive you can convert keywords and columns to lower case Ex:
SELECT email, name, Round ((lower(Char_length(Concat(email, name))) - Char_length(REPLACE ( lower(Concat(email,name)), lower("aasd"), ""))) / Char_length(lower("aasd"))) AS count FROM users Having count >0 ORDER BY count DESC;