| | 1 | = Full Text Search in VitaDiet = |
| | 2 | |
| | 3 | == Introduciton == |
| | 4 | |
| | 5 | Full Text Search (FTS) is a technique for searching natural language text in a database. Unlike a simple LIKE search which matches exact character patterns, FTS understands language — it normalizes words to their root form, ignores common words like "the" and "a", and ranks results by relevance. |
| | 6 | |
| | 7 | For example a LIKE search for '%chicken%' will: |
| | 8 | *Scan every row in the table sequentially |
| | 9 | *Only match the exact string "chicken" |
| | 10 | *Return results in no particular order |
| | 11 | *Become slower as the table grows |
| | 12 | |
| | 13 | A FTS search for 'chicken' will: |
| | 14 | *Use a GIN index to find matches instantly |
| | 15 | *Match "chicken", "chickens", "chickened" |
| | 16 | *Rank results by relevance |
| | 17 | *Perform consistently regardless of table size |
| | 18 | |
| | 19 | For VitaDiet, FTS is used to power the food search feature, allowing users to search 350,000+ foods quickly and accurately. |
| | 20 | |
| | 21 | == How PostgreSQL FTS Works == |
| | 22 | |
| | 23 | PostgreSQL FTS is built around two core data types: |
| | 24 | |
| | 25 | tsvector — a preprocessed representation of a text document. It stores the normalized lexemes (root forms of words) of a text column. For example: |
| | 26 | SELECT to_tsvector('english', 'Grilled Chicken Breast'); |
| | 27 | Result: 'breast':3 'chicken':2 'grill':1 |
| | 28 | *"Grilled" becomes "grill" (stemmed to root form) |
| | 29 | *Numbers indicate the position of each word |
| | 30 | *Stop words like "and", "the" are removed |
| | 31 | |
| | 32 | tsquery — a processed search query. It converts user input into a format that can be matched against a tsvector: |
| | 33 | SELECT plainto_tsquery('english', 'grilled chicken'); |
| | 34 | Result: 'grill' & 'chicken' |
| | 35 | The @@ operator checks if a tsquery matches a tsvector: |
| | 36 | SELECT to_tsvector('english', 'Grilled Chicken Breast') |
| | 37 | @@ plainto_tsquery('english', 'grilled chicken'); |
| | 38 | Result: true |