Sayak Banerjee
Sayak Banerjee

Reputation: 1964

Laravel 4 and full-text search

I have seen quite a few articles on fulltext search in Laravel where users recommend using whereRaw(...) or DB::query(...), but my aim is to remain database agnostic. I understand that a where('col', 'like', '%foo%') is terrible w.r.t. performance.

So I believe I am left with creating my own database index. Is there something that I can do out of the box with Laravel, or some table structure that I can set up to build a faster search mechanism?

Currently, I have a 'main' table with a text column 'data' on which I am planning to run a search on. That is the only column on which I'm doing lookups.

Upvotes: 1

Views: 6536

Answers (3)

Arne
Arne

Reputation: 6240

if queries are not a problem, this is how I did it.

First, include the search form in your view:

{{ Form::open(['method' => 'get']) }}
{{ Form::text('q',Input::get('q')) }}
{{ Form::submit('Search') }}
{{ Form::close() }}

Make sure the table you want to search is MyISAM, you can do this by adding this to a migration:

$table->engine = 'MYISAM';

After that, add this scope to your model and change the columns you want to search:

public function scopeSearch($query,$q) {
  return empty($q) ? $query : $query->whereRaw(
    "MATCH(title,contents,anotherfield) 
      AGAINST(? IN BOOLEAN MODE)",[$q]);
}

In your controller, just add the scope when fetching the data:

$posts = Posts::search(Input::get('q'))->get();

And it should work. In case you need to add pagination, do something like this:

$posts = Posts::search(Input::get('q'))->paginate(30);

And for showing the links in the view, use this code:

{{ $posts->appends(Input::except('page'))->links() }}

This will preserve all the GET params (including the query param) while paginating.

Upvotes: 5

KennyV
KennyV

Reputation: 832

This has been removed from Laravel 4 but as I already said in another question, it can easily be re-implemented as described here: http://creative-punch.net/implementing-laravel-4-full-text-search/

Though the FULLTEXT index does not work everywhere

Upvotes: 1

oBo
oBo

Reputation: 992

Here is a function i use for a simple full-text serach with laravel. If you use mysql rememeber to set the engine to MyISAM on the table.

I have this function in the model file so that i can call User::serachFilter('query'); from the controller.

public static function searchFilter($data, $pageLimit = '5')
    {
        $keyword = !is_array($data) ? array('+'.$data.'*') : $data;
        $matchArray = array('firstName', 'lastName', 'location', 'address');
        $columns = array();
        foreach($matchArray as $column)
        {
            $columns[] = $column;
        }
        $match = implode(',', $columns);
        $result =  self::whereRaw('MATCH('.$match.') AGAINST (? IN BOOLEAN MODE)', $keyword)
                    ->paginate($pageLimit);

        return $result;
    }

Edit: Since you diden't want to use whereRaw, test

    $query = Input::get('search');
    $pageLimit = Input::get('page_limit');

    $search = DB::select("
        select *
        from users
        where match(id, name, email, username)
        against('+{$query}*' IN BOOLEAN MODE)
        limit {$pageLimit}
    ");

    return $search;

Upvotes: 1

Related Questions