search
Product Autocomplete
Type-ahead from a sort key, without a search service.
Autocomplete inside a category, using nothing but the sort key. Names are stored lowercased so ordering is predictable, and a prefix read returns the matches - enough for a type-ahead box, and a long way short of a search engine.
The model
Product
A product, keyed by its lowercased name within a category.
- pk
- CATEGORY#<categoryId>
- sk
- NAME#<normalisedName>
Attributes: displayName (S), pricePence (N), inStock (S)
Access patterns
- QueryNames starting with a prefix
Products in a category whose name begins with what has been typed.
- ScanScan the whole catalogue (for contrast)
The same search without a partition key: every product in the table is read.
- GetItemFetch one product
A single product by category and exact name.
Design notes
Left-anchored only, and that is the limittrade-off
A prefix read finds "coffee" from "cof". It cannot find it from "ffee", because a sort key is ordered from the left and nothing indexes the middle of a string. Every design here is a left-anchored match; wanting the middle is the point at which this technique stops and a search service starts.
Normalised so the ordering is knowablewhy
Sort keys compare byte by byte, so every capital sorts before every lowercase letter and a mixed-case column orders in a way no user expects. The key holds a normalised copy - lowercased, punctuation dropped, whitespace collapsed - while displayName keeps the real thing. Note that the transform is more than case: "Coffee, Decaf" becomes "coffee decaf", because a comma sorts before every letter and would scatter the run. Whatever normalisation you choose, the typed prefix has to go through exactly the same one before it is compared.
The head word is the whole indextrade-off
"Coffee, Decaf" is found by typing "cof". "Ground Coffee Tin" is not - it is filed under "gro", and no amount of typing "cof" will reach it. That inversion in the other names is not a formatting convention, it is the index: choosing which word leads decides what is findable, and anything that must be findable by two words has to be stored twice.
The category keeps the read smalltrade-off
A prefix read stays within a partition, so the category is not a filter - it is what stops the search touching the rest of the catalogue. Run the Scan beside it and the meters show the difference: the same rows come back, having read every product in every category to find them. That is also this design's limit: it cannot search across categories in one read, and a design needing that either duplicates rows per scope or accepts a query per category.
Read the sort-key columntrade-off
The console reads the whole category, since the preview resolves only the partition half of a key condition. The alphabetical run is what matters: a prefix read is a contiguous slice of exactly what you see, which is why it costs only the rows it returns.
Taught in the course
- One query, a whole collection - Items that share a partition key are read together in one Query.
Products in a category whose name begins with what has been typed.
Run an operation to see the raw engine response.
The in-browser engine is a preview build. Transactions, vector search, streams, tags and TTL are among the operations it doesn't implement yet.