Examples
Examples
Real-world implementation patterns and code snippets for integrating pg-smart-search into your application.
Examples
Practical implementations of pg-smart-search in common frameworks and use cases.
Next.js API Route
Create a search API endpoint in your Next.js App Router application.
import { NextRequest, NextResponse } from 'next/server';
import { TrigramSearchEngine, MemoryCacheProvider } from 'pg-smart-search';
import { dbAdapter } from '@/lib/db';
const engine = new TrigramSearchEngine(dbAdapter, {
tableName: 'posts',
searchColumns: ['title', 'content'],
cacheProvider: new MemoryCacheProvider(),
});
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const query = searchParams.get('q');
const cursor = searchParams.get('cursor');
if (!query) {
return NextResponse.json({ error: 'Query parameter "q" is required' }, { status: 400 });
}
// cursor is only valid against the id-ordered STANDARD/LITE path -- see
// /docs/guides/pagination for why it can't be combined with fuzzy fallback.
const results = await engine.search({
query,
cursor: cursor || undefined,
limit: 20,
});
return NextResponse.json(results);
}import type { NextApiRequest, NextApiResponse } from 'next';
import { TrigramSearchEngine, MemoryCacheProvider } from 'pg-smart-search';
import { dbAdapter } from '@/lib/db';
const engine = new TrigramSearchEngine(dbAdapter, {
tableName: 'posts',
searchColumns: ['title', 'content'],
cacheProvider: new MemoryCacheProvider(),
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'GET') return res.status(405).end();
const { q, cursor } = req.query;
if (!q || typeof q !== 'string') {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
const results = await engine.search({
query: q,
cursor: (cursor as string) || undefined,
limit: 20,
});
return res.status(200).json(results);
}E-Commerce Product Search with Filters
Implement a product search that supports filtering by category and price range.
import { TrigramSearchEngine } from "pg-smart-search";
const engine = new TrigramSearchEngine(adapter, {
tableName: "products",
searchColumns: ["name", "description"],
ftsColumn: "search_vector",
});
const results = await engine.search({
query: "wireless headphones",
filters: {
category: "electronics", // plain scalar -> "category" = $n
price: { between: [50, 200] }, // typed operator -> "price" BETWEEN $n AND $n+1
},
limit: 20,
});Pagination with Infinite Scroll
Implement cursor-based pagination for a frontend infinite scroll component. There's no
nextCursor field on the result -- you build the next cursor yourself from the last row's
own id column. Cursor pagination only works against the id-ordered STANDARD/LITE tier; it
throws UnsupportedCursorError on relevance-sorted searches (ADVANCED/VECTOR/fuzzy fallback).
// Initial fetch (page-based, since there's no cursor yet)
const firstPage = await engine.search({
query: "laptop",
limit: 15,
});
// Subsequent fetch: cursor is the id of the last row you saw
const lastRow = firstPage.data[firstPage.data.length - 1] as { id: number };
const nextPage = await engine.search({
query: "laptop",
limit: 15,
cursor: lastRow.id,
});
if (!nextPage.pagination.hasNext) {
console.log("Reached the end of results");
}