13

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.

user7432810
  • 655
  • 3
  • 11
  • 24

5 Answers5

25

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!

Arno van Oordt
  • 2,912
  • 5
  • 33
  • 63
Renan Coelho
  • 1,360
  • 2
  • 20
  • 30
  • The `array_merge()` will fail. The var `$related` is not an array by itself, needs to be like `$related->all()` to return an array. – Chris Jul 03 '20 at 23:01
  • 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! – Renan Coelho Jul 05 '20 at 00:20
  • I just tested it here and it didn't fail. The ->only() method returns an array anyway. – Renan Coelho Jul 05 '20 at 00:48
  • I tested with "php": "^7.3" and "laravel/framework": "^6.0". Didn´t work for me, have to use all() – Chris Jul 06 '20 at 21:30
  • 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')`. – Renan Coelho Jul 08 '20 at 00:24
  • 2
    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. – Jason Apr 28 '22 at 13:21
  • @RenanCoelho, may I ask you to take a look at a Laravel search related question here: https://stackoverflow.com/questions/76485513/laravel-search-with-multiple-keywords-against-multiple-columns-with-the-search ? – Istiaque Ahmed Jun 15 '23 at 22:07
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);
    }
)
Ahmed Aboud
  • 1,232
  • 16
  • 19
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();
0

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

lejlun
  • 4,140
  • 2
  • 15
  • 31
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...

Arm092
  • 580
  • 7
  • 12