Laravel Scout: only search in specific fields
Asked Answered
D

5

14

Laravel Scout: Is there a way that I search in only a specific field?

At the moment this line is working fine:

    $es = Element::search($q)->get();

But it searches title, shortdescription and description fields. I need it to only search in title field.

Durtschi answered 1/9, 2017 at 16:34 Comment(0)
S
26

You just need to change your toSearchableArray method from your model by adding the following code:

/**
 * Get the indexable data array for the model.
 *
 * @return array
 */
public function toSearchableArray()
{
    $array = $this->only('title', 'description');

    $related = $this->user->only('name', 'email');

    // Customize array...

    return array_merge($array, $related);
}

Then call php artisan scout:import "App\YourModel" to reindex the new records. 

Note:

  • $this->only('title', 'description') will search only for its title and description fields
  • $this->user->only('name', 'email') will also search for its name and email from a related Model

So you can retrieve the related data by adding ->load('user') in your search method like the following code:

public function search(Request $request)
{
    $query = $request->get('q');

    return Task::search($query)->get()->load('user');
}

UPDATE

If you're trying to retrieve the data using ->paginate() method, you must need to load the relations separately:

...
$tasks = Task::search($query)->paginate($request->get('per_page'));

$tasks->load('user');

return $tasks;

Enjoy!

Salim answered 25/11, 2017 at 13:20 Comment(7)
The array_merge() will fail. The var $related is not an array by itself, needs to be like $related->all() to return an array.Mahmoud
The code was tested before publishing. Perhaps Laravel has updated it in new versions. I'll try and update the answer. Thanks for the report!Salim
I just tested it here and it didn't fail. The ->only() method returns an array anyway.Salim
I tested with "php": "^7.3" and "laravel/framework": "^6.0". Didn´t work for me, have to use all()Mahmoud
If you have a collection, you need to map it and then use the ->only() method like this: \App\User::all()->map->only('name')->all(). But If you have only one instance of model you just need the ->only() method like this: \App\User::first()->only('name').Salim
This is a different question, and tells us how to remove fields from the search index. How do we remove feilds from the search without removing them from the index? The OP may still want to search on other fields in other contexts, or use a where() filter on a field, such as a status field.Cranio
@RenanCoelho, may I ask you to take a look at a Laravel search related question here: #76486013 ?Jandy
N
1

You can do that by adding a callback function to the scout builder instance,

Person::search($searchString)->query(function($query) { 
       $query->addSelect(['title']);  
})->get();

Worked on laravel 7

Nomination answered 14/8, 2021 at 10:17 Comment(0)
F
1

for meilisearch this worked

Element::search('test',
    function ($searchEngine, string $query, array $options) use ($filter) {
        $searchEngine->resetSearchableAttributes();
        $searchEngine->updateSearchableAttributes(['field_name']);
        return $searchEngine->search($query, $options);
    }
)
Fenton answered 16/9, 2021 at 8:38 Comment(2)
$searchEngine->updateSearchableAttributes(['*']); might not work instantlyFenton
use app(\Laravel\Scout\EngineManager::class)->forgetDrivers();Fenton
S
0

You can do that by adding a callback function to the scout builder instance,

Person::search($searchString)->query(function($query) { 
       $query->select(['title']);  
})->get();
Snuffle answered 7/6, 2021 at 17:11 Comment(0)
T
0

If you want standard query result, but search only in a specific column (field), you can try this solution:

        Element::search($query)->rule(function($builder) {
            return [
                'must' => [
                    'match' => [
                        'some_column_name' => $builder->query
                    ]
                ]
            ];
        });

Tested on Laravel 6, but I think it will work on later versions to...

Traceetracer answered 3/5, 2022 at 7:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.