Enabling Full-Text Search with PostgreSQL in Laravel

Why Use PostgreSQL for Full-Text Search in Laravel

When building apps with searchable content—blogs, marketplaces, knowledge bases—search is no longer optional. While Laravel supports packages like Scout and Algolia, PostgreSQL’s built-in full-text search offers a powerful, self-contained solution without third-party APIs.

PostgreSQL supports advanced text indexing using tsvector and tsquery, ideal for Laravel applications that need performant, scalable search.

PostgreSQL gives you deep, native search without leaving your database. Laravel makes it approachable.


Key Takeaways

  • Enable powerful, native search without third-party services
  • Use tsvector columns and GIN indexes for optimized queries
  • Integrate with Laravel using Eloquent or raw queries
  • Works great with multilingual content

Setting Up PostgreSQL Full-Text Search in Laravel

Configure PostgreSQL in Laravel

Ensure your .env file is using PostgreSQL:

DB_CONNECTION=pgsql

Update .env and run:

php artisan migrate

Create a Model and Migration

Example: Let’s say you’re building a searchable posts table.

php artisan make:model Post -m

Migration example with tsvector:

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->tsvector('search_vector')->nullable();
    $table->timestamps();
});

To support tsvector, create a macro in a migration stub or use a custom SQL query in your migration.

Generate the Search Vector Automatically

Use a database trigger:

CREATE FUNCTION posts_search_vector() RETURNS trigger AS $$
BEGIN
  NEW.search_vector :=
    setweight(to_tsvector('english', coalesce(NEW.title, '')), 'A') ||
    setweight(to_tsvector('english', coalesce(NEW.body, '')), 'B');
  RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
  ON posts FOR EACH ROW EXECUTE PROCEDURE posts_search_vector();

Add a GIN Index

CREATE INDEX posts_search_vector_index
  ON posts USING GIN (search_vector);

Performing a Full-Text Search Query in Laravel

You can use Eloquent or raw queries.

Using Raw SQL

$results = DB::table('posts')
  ->whereRaw("search_vector @@ plainto_tsquery('english', ?)", [$search])
  ->get();

Using a Scope in Eloquent

// Post.php
public function scopeSearch($query, $term)
{
    return $query->whereRaw(
        "search_vector @@ plainto_tsquery('english', ?)",
        [$term]
    );
}
// Usage:
Post::search('laravel')->get();

Blade Example: Search View

<form method="GET" action="{{ route('posts.index') }}">
  <input type="text" name="search" placeholder="Search posts...">
  <button type="submit">Search</button>
</form>
@if(request('search'))
  <p>Searching for: <strong>{{ request('search') }}</strong></p>
@endif
@foreach($posts as $post)
  <div>
    <h2>{{ $post->title }}</h2>
    <p>{{ Str::limit($post->body, 150) }}</p>
  </div>
@endforeach

Advanced Tips

Language Configuration

PostgreSQL supports many languages:

SELECT to_tsvector('french', 'bonjour tout le monde');

Match your application’s locale.

Weighting and Ranking

Use ts_rank to order results:

$posts = DB::table('posts')
    ->select('*', DB::raw("ts_rank(search_vector, plainto_tsquery('english', ?)) as rank"))
    ->whereRaw("search_vector @@ plainto_tsquery('english', ?)", [$term, $term])
    ->orderByDesc('rank')
    ->get();

Full-Text Search vs Laravel Scout

Feature PostgreSQL Full-Text Laravel Scout + Algolia
Cost Free Subscription required
Setup DB triggers and indexes API + indexing config
Speed Fast for mid-scale apps Super fast
Customization High (weights, language) Low-medium
Offline support ✅ Yes ❌ No

Use PostgreSQL when:

  • You need built-in search for internal tools, dashboards, or apps with rich text
  • You want full control over indexing

Use Laravel Scout when:

  • You want fuzzy matching, typo correction, and external APIs

FAQ

Is PostgreSQL full-text search fast? Yes, especially when combined with GIN indexes.

Does Laravel support tsvector out of the box? Not directly, but it integrates well through raw queries or scopes.

Can I use Scout and PostgreSQL together? Yes, but it’s typically one or the other based on your use case.

What if I need multilingual search? PostgreSQL supports multiple language configurations in to_tsvector() and tsquery().


Helpful Resources


Conclusion

PostgreSQL full-text search is an underused but powerful feature in Laravel applications. With minimal setup—just a migration, a trigger, and a few lines of SQL—you can turn any table into a search powerhouse.

Whether you’re building a blog, marketplace, or dashboard, full-text search in PostgreSQL is fast, reliable, and fully native to your app. If you’re already using PostgreSQL with Laravel, you’re only a few steps away from excellent search.

Enabling Full-Text Search with PostgreSQL in Laravel
Chat with me