Mastering Postgres
Introduction
Introduction to the course
Overview of course structure
Postgres vs. everyone
The psql CLI
Data Types
Introduction to schema
Integers
Numeric
Floating point
Storing money
NaNs and infinity
Casting types
Characters types
Check constraints
Domain types
Charsets and collations
Binary data
UUIDs
Boolean
Enums
Timestamps
Timezones
Dates and times
Advanced Data Types
Intervals
Serial type
Sequences
Identity
Network and mac addresses
JSON
Arrays
Generated columns
Text search types
Bit string
Ranges
Composite types
Nulls
Unique constraints
Exclusion constraints
Foreign key constraints
Indexing
Introduction to indexes
Heaps and CTIDs
B-Tree overview
Primary keys vs. secondary indexes
Primary key types
Where to add indexes
Index selectivity
Composite indexes
Composite range
Combining multiple indexes
Covering indexes
Partial indexes
Index ordering
Ordering nulls in indexes
Advanced Indexing
Functional indexes
Duplicate indexes
Hash indexes
Naming indexes
Understanding Query Plans
Introduction to explain
Explain structure
Scan nodes
Costs and rows
Explain analyze
Generating Results
Introduction to queries
Cross joins
Inner joins
Outer joins
Subqueries
Lateral joins
ROWS FROM
Filling gaps in sequences
Subquery elimination
Combining queries
Set generating functions
Indexing joins
Advanced SQL
Introduction to advanced SQL
Grouping
Grouping sets, rollups, cubes
Window functions
CTEs
CTEs with window functions
Recursive CTE
Hierarchical recursive CTE
Handling nulls
Row value syntax
Views
Materialized views
Removing duplicate rows
Upsert
Returning keyword
COALESCE + generated column
Full Text Search
Introduction to full text search
Searching with LIKE
Vectors, queries, and ranks
Websearch
Ranking
Indexing full text search
Highlighting
Advanced JSON
Intro to JSON
JSON vs JSONB
Validating JSON
Creating JSON objects + arrays
JSON extraction
JSON containment
JSON existence
JSON recordset
Updating JSON
Indexing JSON parts
GIN index
Vectors (pgvector)
Intro to pgvector
Vector embedding columns
Find related articles
Upsert vector embedding
Semantic search
Other operators
Vector indexes
Outro
Thank you
Bonus interviews
Heroku's glory days & Postgres vs the world (with Craig Kerstiens)
Creating a Postgres platform with Monica & Tudor from Xata.io
Bootstrapping an email service provider (with Jesse Hanley)
Locked video

Please purchase the course to watch this video.

Video thumbnail
Full Text Search
Highlighting

Full Course

$
349
$399
USD, one-time fee
Really enjoying Aaron Francis' "Mastering Postgres". It's information-dense, very approachable, and well-produced.
Daniel Bachhuber
Daniel Bachhuber

PostgreSQL database platform

Shorten dev cycles with branching and zero-downtime schema migrations.

Test Data

I've made my test data available for you to use and follow along.

Download
or
Use on Xata

Summary

Improve search engine user experience by using Postgres' ts_headline function to dynamically highlight search terms as users type. This allows users to easily see which parts of the results match their query, with the option to style the highlights using custom tags for better presentation. By applying this to titles and plots, you provide useful snippets, enhancing the interface and overall usability.

Links

Highlighting results documentation

Video Transcript

One of the things we need to think about when we're building out this search engine is the user experience. We've already kinda gotten there with the web search to tsquery. We kinda got there with the GIN index, so now we have some nice searching, some nice performance.

I think one of the final things that we need to think about for user experience is notifying or showing the user the matches as they're typing. If somebody is typing Star Wars and a title pops up, it would be nice if Star and Wars were highlighted so that you can see your search query lining up with all of the results and see which parts match your query. Fortunately, Postgres has a built-in highlighting function that I'm gonna show you how to use right now.

The highlighting function is called ts_headline, and so we're gonna do ts_headline and we can do this across different columns. We don't actually use the vectors either stored or generated. We don't use those vectors. We just use the original document as they call it. We're gonna pass in, again, we're gonna pass in English. The next thing is the document. In this case, we're gonna pass in title because this is just going to be the title highlight, so we can say as title_highlighted. That will be that. The final thing is we do need to pass in the tsquery. We're just gonna use our same query here. If we run that, we'll see that it worked almost immediately. We get Star and Wars highlighted along with Wars down here. Everything is surrounded with these bold markers, which is fine.

I would rather something maybe a little bit more semantic or something a little bit more controllable on the front-end. I'm just going to change it. Instead of using bold, we have the option, the fourth parameter is we can pass a bunch of different configuration options, including the opening mark, the closing mark, the minimum words, whether or not we should include the entire document in the result. All kinds of stuff like that. We're just gonna look at changing the opening and closing marks. We do that in this final argument here. We're gonna say StartSel equals, we're gonna say, let's do a start of the selection equals mark and a stop of the selection equals end mark. It's just comma separated. You have your option name with equals and then the value. I'll put a link down in the description because there are some other options that you can pass through here, some of which may be helpful.

These are the ones that I really care about. We're returning it with these mark tags, which is a little bit easier to style on the front-end and doesn't necessarily mean it's going to be bold. Maybe we do a yellow background or something like that. I do like that this ts_headline operates on the original document rather than the vectors, because as you'll remember, we're searching across title and plot, but we can return a title highlighted and then optionally return a plot highlighted as well.

If you do highlight over a large document, it is going to compress it down and leave some ellipses in there, which is controllable. But that's really nice 'cause we can get the entire title back and show those highlights and then have some sort of excerpt or snippet from the plot and just show those highlights, which makes for a really nice user interface.