Laravel query builder: reverse of "LIKE"? - laravel-5

I need the reverse of a LIKE comparison. For example, if my database contains a person with firstName "Daniel" and I search for first name "dan" then I want to get a hit. The query works when I use
->where('firstName', 'like', '%'.$searchTerm.'%')
What would I use if my database contains "Dan" and I want to get a hit when I search for "Daniel", but not when I search for "Steve"? Basically, I want the effect of putting the wildcard % around the field instead of around the search term.
I am using the query builder in Laravel 5.6
[edited for clarity]

You can swap column and search term:
->whereRaw("? LIKE CONCAT('%', `firstName`, '%')", [$searchTerm]);

Related

Get data from two different database columns

i have tow column in my sql and use this query to search
$Person->where('name','LIKE',"%{$keyword}%")
->orWhere('family_Name','LIKE',"%{$keyword}%")
->orWhere('id',$keyword);
but if user type name and family name together then result is null
how can i get where from sum of tow column? or any other way
If I understood correctly, a raw sql command like the one below might work for you.
$person->where(DB::raw('CONCAT_WS(" ", name, family_Name)'), 'like', '%'.$keyword.'%')->get();
I assume you want search "John Doe". You put "John" at column name and "Doe" at family_name.
So, you can add CONCAT_WS() for this.
$Person
->where('name','LIKE',"%{$keyword}%")
->orWhere('family_Name','LIKE',"%{$keyword}%")
->where(DB::raw('CONCAT_WS(" ", name, family_name)'), 'like', "%{$keyword}%") // <-- here
->orWhere('id',$keyword);

Laravel eloquent search and order by best matching

I have a products table in my ecommerce website. When customers search products by name, I execute the following query:
$products = Product::where('name', 'like', '%'.$query.'%')->get();
Now, I see the result contains only matched rows with customer's $query. But the result is not ordered by the best matching as like google. How should I change my query to get products ordered by best matching?
First of all, best match is a bit ambiguous.
However any solution will always include the usage of multiple orderByRaw calls.
Example:
$products = Product::where('name', 'like', '%'.$query.'%')
->orderByRaw('name like ? desc', $query)
->orderByRaw('instr(name,?) asc', $query)
->orderBy('name')
->get();
Basically, it orders on the name match first (still using like to allow wildcards in the search string, if not needed use =).
Then it orders the substring position of the query it found in the name col, make sure to order asc since lower is better. At least in my definition of best match.
Also notice the usage of the ? parameter. Using it like this ->orderByRaw('name like '.$query.' desc') will make it vulnerable to SQL injection!
Take into account that ordering on multiple subqueries can be costly!

I want to extract the first five data that match the where clause from Laravel relationships

I'd like to do something like this with Laravel's Eloquent:relationship, but it doesn't work.
$playlist->setRelation('tags', $playlist->tags->where('privacySetting', 'public')->take(5));
It works without where clause, but I want to retrieve the first 5 data in the tags relationship table that match the where clause.
How can I do this?
Laravel version is 7.28.1.
this will select top 5 based on criteria from model
$playlist = Playlist::with(['tags' => function($filter){
return $filter->where('privacySetting', 'public')
->take(5);
}])
->get();
//try dd($playlist);

Efficient way to query database with multiple conditions in laravel

Is it possible to make this a single query?
$yl_min = DB::connection($this->db2)->table('historical')
->where([['slug','=',$crypto_id],['low_usd','!=', null]])
->whereBetween('created_time',[$this->range_1y,$this->hislatest])
->min('low_usd');
$yl = DB::connection($this->db2)->table('historical')
->select('id','coin','low_usd','created_time','created_at')
->where([['slug','=',$crypto_id],['low_usd',$yl_min]])
->whereBetween('created_time',[$this->range_1y,$this->hislatest])
->first();
I've tried this but no luck:
$yl = DB::connection($this->db2)->table('historical')
->select('id','coin','created_time','created_at',DB::raw('SELECT MIN(low_usd) as low_usd'))
->where([['slug','=',$crypto_id],['low_usd','!=', null]])
->whereBetween('created_time',[$this->range_1y,$this->hislatest])
->first();
After looking at your query code, I found the two query condition is same, and you just want to get min low_usd record,
I think you can just use the multiple condition and ORDER BY low_usd ASC, then take the first one:
$yl = DB::connection($this->db2)->table('historical')
->where([['slug','=',$crypto_id],['low_usd','!=', null]])
->whereBetween('created_time',[$this->range_1y,$this->hislatest])
->orderBy('low_usd','asc')
->select('id','coin','low_usd','created_time','created_at')
->first();
After this, if you want to make this query more efficient,
you need to add index on slug, low_usd, created_time

Search query from joined table in Laravel 5.3

I have a books table that contains many subject on my subjects table (one-to-many relationship).
I tried to join my tables like this:
$book = Book::latest()
->leftjoin('subjects', 'books.id', '=', 'subjects.book_id')
->select('books.*', 'subjects.subject')
->where('subject', 'like', '%' .$search. '%')
->paginate(20);
I want a search query that will display the books having subjects matched form the $search variable. However, it keeps displaying a book redundantly depending on how many subjects of a book that matched on the $search variable since a book has many subjects.
I only want to display a book once, regardless of how many subjects the book matched.
This image below was the output of the search query I made, the value of the $search= ""
On the second image notice that I search "a" on the search box:
The book entitled "Special Education assessment: Issues strategies affecting today's classrooms" (see it on the first image; it was being redundant 6 times since the subjects of that book was 6)
To display a book only once you have to group by book id (or any other unique column)
->groupBy('books.id');
Mind you, as mentioned in the MySQL doc here
SQL92 and earlier does not permit queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are not named in the GROUP BY clause.
Hence the error message 'bisu_ccc_library.books.ISBN' isn't in GROUP BY
To bypass this, turn off strict in Laravel and everything will work nicely.
Go to config/database.php and in the mysql configuration array, change strict => true to strict => false
I think you want to use distinct for your select
$book = Book::latest()
->leftjoin('subjects', 'books.id', '=', 'subjects.book_id')
->select('books.*', 'subjects.subject')
->distinct()
->where('subject', 'like', '%' .$search. '%')
->paginate(20);
Just like in regular SQL (which it will translate to) it will "Force the query to only return distinct results." (from laravel api docs)
The SELECT DISTINCT statement is used to return only distinct
(different) values.
Inside a table, a column often contains many duplicate values; and
sometimes you only want to list the different (distinct) values.
The SELECT DISTINCT statement is used to return only distinct
(different) values. - W3Schools

Resources