Full-text search is a technique used to analyze strings, documents, or entire database columns to deliver flexible and intelligent search results. Instead of relying on string matching, full-text search looks at context, synonyms, and word variations.
So while a regular SQL query might match only "run", a full-text search can also match "running", "ran", or "runner" depending on the configuration.
Full-text search is supported by many databases including PostgreSQL, MySQL, MongoDB, and specialized engines like Elastic-search and Meilisearch.
In this article, we focus on PostgreSQL full-text search using TypeORM + Node.js.
Benefits of full-text search
-
Search Large Bodies of text quickly: If you have large text fields, like blog posts, recipes, product descriptions, or comments, full-text search lets you efficiently check which documents contain certain keywords.
Example: Search for
"chicken"→ return all recipes that mention chicken anywhere in the text. -
Better and more flexible search results: Full-text search handles imperfections in queries:
- Typing
"run shoes"can still match"running shoes" - Searching
"comput"can match"computer"and"computing"
This dramatically improves user experience on e-commerce, blogs, dashboards, and enterprise search tools.
- Typing
When to use full-text search?
- You want flexibility, not exact matches; Searching products, users, notes, events, or blog posts where partial matches are okay.
- When you want to index large bodies of text and return results based on if a certain word or keyword is contained within that body of text ( returning a list of recipes that contain chicken).
Setting up full-text search in typeorm + postgres + nodejs
Below is an example using a simple Recipe entity that supports searching on both the name and description fields.
- Create the Recipe Entity
@Entity() export class Recipe { @PrimaryGeneratedColumn() id: number; @Index({fulltext: true}) @Column("varchar") name: string; @Index({fulltext: true}) @Column("varchar") description: string; } - Query the database using a the typeorm query-builder to return data based on the provided search query
async function searchRecipes(searchQuery: string) { return dataSource .getRepository(Recipe) .createQueryBuilder("recipe") .where(` to_tsvector('english', recipe.name || ' ' || recipe.description) @@ plainto_tsquery('english', :query) `) .setParameter("query", searchQuery) .getMany(); } In raw SQL this would look something like this
SELECT * FROM recipe WHERE to_tsvector(name || " " || description) @@ to_tsquery("Chicken"); This will then return all the recipes with chicken in it’s description or name
Top comments (3)
very detailed!
Nice read
Nice read