Something like this should work:
$suggestions = Post::where('title', $query)
->orWhere('title', 'ilike', $looseQuery)
->limit(5)
->orderByRaw('(title = ?) DESC, LENGTH(title)', $title)
->get();
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I am using PostgreSQL.
Situation: Say I have quite a few posts with "Shoes" in the title but there is also a post where the title is only the word "Shoes".
Aim; I want to perform a database query where it shows the post with the exact match of "Shoes" first, and then all other results where the word "Shoes" can be anywhere within the title.
Attempt: To do this I made the following code:
public function findPost ($query) {
$looseQuery = '%' . $query . '%';
$suggestions = Post::where('title', $query)
->orWhere('title', 'ilike', $looseQuery)
->limit(5)
->get();
return $suggestions;
}
The SQL for this is:
select * from "posts" where ("title" = ? or "title"::text ilike ?) limit 5;
Issue: However, when I run this, the exact match comes at the end of the collection rather than the beginning? As a result if there are more than 5 posts satisfying the $looseQuery, then the exact match doesn't show up at all.
How can I get the exact match first?
Something like this should work:
$suggestions = Post::where('title', $query)
->orWhere('title', 'ilike', $looseQuery)
->limit(5)
->orderByRaw('(title = ?) DESC, LENGTH(title)', $title)
->get();
Please or to participate in this conversation.