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
tsvectorcolumns 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.