I would like to improve my search function.
Lets say for example the user types in "Letter contract" and in my database i have saved the following string "Letter employment contract". Using the following code will not return anything:
Letter::where('title', 'LIKE', '%' . $search . '%)->get()
Since the search is not looking into "Letter" alone and "Contract" alone in the context.
Anyways i can fix this?
Update
I tried the following code sample but still didn't get anywhere
$searchValues = preg_split('/\s+/', $this->attributes['q'], -1, PREG_SPLIT_NO_EMPTY);
$model = $model->whereTranslationLike('title', "%{$this->attributes['q']}%");
foreach ($searchValues as $value) {
$model->orWhereTranslationLike('title', "%{$value}%");
}
A very naive (but simple) solution would be first to split the search string into individual words, then adding them to the query individually.
$words = explode(' ', $search);
$query = Letter::query();
foreach ($words as $word) {
$query->where('title', 'LIKE', "%{$word}%");
}
$letters = $query->get();
This implementation doesn't scale very well, but it should get you thinking in the right direction.
There is no issue with your first code but for me, if I wanted to do like you, my code will be like so
$letters = Letter::where("title", "LIKE", "%{$search}%")->get()
I wish this syntax helps you.
Related
I have a model that has a field type which consists of several words. The string looks like this: modern premium hot.
How to get relevant results if I want to filter it with an array like this one:
$filter = [0 => 'modern', 1 => 'hot'];
$search = implode(' ', $filter);
$results = Model::where('type', $search)->get();
The above example will not return anything because it will try to match modern premium hot with modern hot and its not the same, but how to get all relevant results that contain the words modern and hot at the same time in the type fields?
In other words how to get all results that have all elements of the array in the type field, which is a string?
Maybe you need a fulltext service like Elastic Search or Algolia, or even look at fulltext search on your database engine (assuming MySQL, check this link).
But if you really need to move on as it is going, you may try something like that:
$query = Model::query();
foreach ($filter as $term) {
$query->orWhere('type', 'LIKE', "%{$term}%");
}
$results = $query->get();
You use orWhere()
$filter = [0 => 'modern', 1 => 'hot'];
$query= Model::query();
foreach($filter as $term) {
$query->orWhere('type', $term);
}
$results = $query->get();
if you have other where() in your query, use this
$filter = [0 => 'modern', 1 => 'hot'];
$results = Model::where(function($query) use($filter) {
foreach($filter as $term) {
$query->orWhere('type', $term);
}
})
//->where(....)
->get();
I would like to LIKE search.
If 'product' column has "AQ" string display data.
I wrote below code but I couldn't get any record.
Could you teach me right code please?
public function w_mo_fb_m()
{
$word = "AQ";
$images = ImageGallery::where('product', 'like', "%$word%")->orderBy('id', 'desc')->get();
return view('w_mo_fb_m',compact('images'));
}
How about try this.
where('product', 'LIKE', '%'.$word.'%')
//or
where('product', 'LIKE', "%{$word}%")
If this still not working you may need to run raw SQL to see if you can get any record. (you need to replace ImageGallery with your actual table name)
DB::select('select * from ImageGallery where product LIKE = ?', ['%'.$word.'%']);
I am using eloquent query to filter data. My query is like this and it is working perfectly for now.
$users = User::where('username','LIKE','%'.request('username').'%')
->where('first_name','LIKE','%'.request('first_name').'%')
->where('last_name','LIKE','%'.request('last_name').'%')
->where('gender','LIKE','%'.request('gender').'%')
->where('password','LIKE','%'.request('password').'%')
->SimplePaginate(15);
My request data was like this.
However I need to update this query for dynamic fields. There can be different fields. What I did was to send the request in an associative array. So, my request data turned into like this,
What I intend to do is to put all request data in a search array. Then use a loop to run like the above query. How can I do that?
P.S. I checked in the forum and found some similar questions. Some of them are outdated. Others didn't solve my problem.
If I understand you right you can do like this:
$search = request('search', []);
$users = User::query();
foreach($search as $field=>$value)
{
$users = $users->where($field,'LIKE','%'.$value.'%');
}
$users = $users->SimplePaginate(15);
You can try this.
$search = $request->get('search');
User::where(function ($q) use ($search){
foreach ($search as $key=>$value) {
if($value != null ){
$q->where($key, 'like', "%{$value}%");
}
}
})->get();
The where() clause can also accept an array. With that in mind, you could map over your search parameters and convert it to the format you want and then feed it into the query.
For example:
$search = [
'first_name' => 'John',
'last_name' => 'Smith'
];
$filters = collect($search)->map(function($value, $key) {
return [$key, 'LIKE', "%{$value}%"];
})->values()->toArray();
return User::where($filters)->SimplePaginate(15);
This is my controller
$term = $request->get('q');
// return $request->q;
$products = Post::whereHas('user', function($query) use($term) {
$query->where('name', 'like', '%'.$term.'%');
})->orWhere('tags','LIKE','%'.$term.'%')->get();
return view('pages.search', compact('products','users'));
This is working good for single keyword search. But I want to use it for multiple keywords. Like laravel php etc. Please guide me when I search multiple values like abc php laravel or anything then it should work. If tags exists in different column like php is present in 1st column and laravel is in next column when I search php laravel then it should show me both column values.
There is probably a better way to do this, like using CloudSearch/Algolia, but this is a solution that has worked for us:
// Split the terms by word.
$terms = explode(" ", request('q'));
$products = Post::query()
->whereHas('user', function ($query) use ($terms) {
foreach ($terms as $term) {
// Loop over the terms and do a search for each.
$query->where('name', 'like', '%' . $term . '%');
}
})
->orWhere(function ($query) use ($terms) {
foreach ($terms as $term) {
$query->where('tags', 'like', '%' . $term . '%');
}
})
->get();
I spent lots of time on this over the past couple days, and here is my solution. It's similar to these other ones but different, so it may be of value for someone one day:
I have a Vue component that makes a GET request, so $request->get('searchTerms') comes from <input name="searchTerms"> in the HTML form submit.
I wanted to allow to user to control which fields were going to be searched, so that's why $search_terms is an array of columns to search.
I wanted it so if the user searched for "McDonalds 604" that it would filter the list of records and show two different matches for that search. One matching "McDonalds" for business_name and one matching "604" for the area code of the phone_number. This would ensure the user would get everything related in case they only knew some fragments.
The goal was to iterate over the search terms and also to iterate over the search fields (columns) with a generic formula that could be applied from any number of search terms and columns, dynamic at runtime.
$search_fields = ['project_name', 'business_name', 'phone_number'];
$search_terms = explode(' ', $request->get('searchTerms'));
$query = Campaign::query();
foreach ($search_terms as $term) {
$query->orWhere(function ($query) use ($search_fields, $term) {
foreach ($search_fields as $field) {
$query->orWhere($field, 'LIKE', '%' . $term . '%');
}
});
}
$filtered = $query->get();
I would recommend reading through the query docs for Laravel because it will give you better intuition about this task: https://laravel.com/docs/5.6/queries
In the above code, we are using parameter grouping and it changes the characteristics of the algorithm if you use where vs. orWhere.
Bonus Factoids
I also highly recommend testing your SQL statements using $query->toSql() and $query->getBindings(). You can put those in place of $query->get() to see what the SQL statement it is generating will look like and what the parameter bindings are. getBindings() will show you what the values of the ? are in toSql().
You need to prepare the $terms array first, then just iterate over it and add orWhere() clauses.
I've just tested it and for whereHas() closure you need to use where() for the first term and orWhere()for the rest of it to make it work:
$posts = Post::whereHas('user', function($q) use($terms) {
$q->where('name', 'like', '%' . $term .'%');
foreach (array_slice($terms, 1) as $term) {
$q->orWhere('name', 'like', '%' . $term .'%');
}
});
foreach ($terms as $term) {
$posts->orWhere('tags', 'like', '%' . $term . '%');
}
$posts = $posts->get();
If you'll decide to use = instead of like, just use whereIn() instead of building query with a bunch of orWhere().
How can I do a Like-query, with multiple values to search for?
$searchWords = explode(' ', Input::get('search'));
Then I get an array of words that were given for the search.
How can I pass it in this:
$pages = Page::where('content', 'LIKE', '%'.$singleWord.'%')->distinct()->get();
A loop can't work, then it overwrites the $pages always; then it keeps always the latest search:
foreach($searchWords as $word){
$pages = Page::where('content', 'LIKE', '%'.$word.'%')->distinct()->get();
}
A loop is the solution but you only need to add the where condition without executing the query
$pages = Page::query();
foreach($searchWords as $word){
$pages->orWhere('content', 'LIKE', '%'.$word.'%');
}
$pages = $pages->distinct()->get();
i will code it for you :
$pages = Page->where(function($query) use($word){
foreach($searchWords as $word){
$query->orWhere('content', 'LIKE', '%'.$word.'%');
}
})->get();
you can try that , i hope that will help :)