Learn · The Art of Not Looking
budding
The Back of the Book
An index does not make reading faster. It performs a different computation: turning documents inside out so a query can begin with the word instead of the page.
Knowledge is of two kinds. We know a subject ourselves, or we know where we can find information upon it.
— Samuel Johnson, in James Boswell's Life of Johnson, 18 April 1775
This is the first chapter in a book about search from first principles. You will build the smallest useful text index by hand, state the relation it transposes, trace its construction algorithm, prove why its postings stay correct, and count the work saved on three queries. You will also reject four tempting substitutes: scanning faster, storing only a vocabulary, sorting whole documents, and beginning with embeddings. The next chapter will expose the contract hidden inside the apparently simple phrase “the same word.”
The bargain at the back
Open a nonfiction book near its final pages. The index does not say:
page 12 fox, field, tracks
page 41 index, pages, words
page 73 evidence, search
That would merely repeat the book's forward direction: page first, words second. The actual index reverses the question:
evidence 73
field 12, 19
fox 12, 19
index 41, 88
Now a reader who starts with fox can jump directly to two pages. The book was not scanned more quickly. A different relation was prepared in advance.
Inverted index — a dictionary from terms to the documents or positions in which they occur. It inverts the forward relation from documents to their terms. The opening chapters of Manning, Raghavan, and Schütze develop the standard form.
Here is the corpus that will travel through the book. It is deliberately small enough to fit on one sheet of paper.
| ID | Title | Body |
|---|---|---|
| 1 | A Field Guide | a quick fox crosses the quiet field |
| 2 | Fox Tracks | a fox leaves tracks across a field |
| 3 | The Back of the Book | an index maps words to pages |
| 4 | Finding a Phrase | word order turns a match into a phrase |
| 5 | Search for Evidence | machines retrieve evidence before answering |
| 6 | The Patient Reader | a reader searches the index before scanning pages |
| 7 | Rare Words | rare words can carry more evidence |
| 8 | Fast Answers | a bound proves which candidates cannot win |
For the moment, lowercase body words separated by spaces are the terms. Titles will matter later, but not yet. Under that intentionally crude rule, the corpus contains 54 term occurrences.
Before reading on, predict the index entry for field.
field before constructing the index.The transpose
Write the collection as a binary relation
where means that document contains term . A forward view fixes a document and asks for its terms:
An inverted view fixes a term and asks for its documents:
Nothing has been approximated. The same pairs are grouped by their other coordinate. In a matrix picture, documents are rows, terms are columns, and indexing transposes the useful access direction.
Transpose — exchange the two coordinates of a relation: every pair becomes . This is the same operation that reflects a matrix across its main diagonal. Learn more.
The physical index has two parts:
- the dictionary stores each distinct term and finds its list;
- a postings list stores the increasing document IDs for one term.
Posting — one recorded occurrence in an inverted index. In the basic document-level index it is a document ID associated with a term; later it may also carry frequency, positions, fields, or a score contribution. Learn more.
For part of the corpus, the result is:
| Term | Postings |
|---|---|
| evidence | 5, 7 |
| field | 1, 2 |
| fox | 1, 2 |
| index | 3, 6 |
| pages | 3, 6 |
| rare | 7 |
| words | 3, 7 |
The dictionary answers “does this term exist, and where is its list?” The list answers “which documents contain it?” Keeping those responsibilities separate will matter when the dictionary becomes an automaton and the postings become compressed integer sequences.
An inverted index is not a faster way to read every document. It is the transposed relation from terms to locations, prepared once so each later query can begin at the term and avoid documents that cannot match.
Build it once
The smallest construction algorithm emits one pair for every term occurrence, sorts the pairs, and groups equal terms. Let be the number of term occurrences in the collection.
Pair-sort construction of a document-level inverted index
BUILD-INVERTED-INDEX(D)
Input: documents D[1:n], each represented by its analyzed terms
Output: dictionary mapping each term to its sorted postings list
pairs ← empty sequence
for each document d in D
seen ← empty set
for each analyzed term t in d
if t is not in seen
append (t, d.id) to pairs
add t to seen
sort pairs by (term, document ID)
index ← empty dictionary
for each maximal run r in pairs with the same term
index[r.term] ← document IDs from r
return indexThe per-document seen set prevents repeated words from duplicating a document ID in this basic Boolean index. A later ranking chapter will retain frequency instead of discarding it.
The algorithm's dominant generic step is sorting at most pairs, for comparisons and stored pairs. The final grouping pass is linear. This is a teaching construction, not the last word: large indexers use blocked sorting or single-pass in-memory indexing so the collection need not fit in memory. The relation and the correctness argument remain the same.
Why is each output list correct? Keep this invariant while scanning a sorted run for term :
After consuming the first pairs of 's run, the output contains exactly the document IDs from those pairs, once each, in increasing order.
It is true before the first pair because both sets are empty. The next pair has the same term, its document ID is not duplicated because construction emitted at most one pair per document, and sorting makes it no smaller than the previous ID. Appending it preserves exact membership, uniqueness, and order. When the run ends, construction has emitted a pair for every document that contains , so the list is exactly .
This proof is modest, but it buys three later algorithms. Intersection can rely on increasing IDs. Gap encoding can rely on nonnegative differences. A query can rely on absence from the list meaning absence from the document under the same analysis rule.
Count before timing
Suppose a query asks for one exact term. A scan inspects all 54 term occurrences, even when only two documents can match. The inverted lookup reads the dictionary entry and then only that term's postings.
| Query | Term inspections under a full scan | Posting entries reached |
|---|---|---|
index | 54 | 2: documents 3 and 6 |
fox AND field | 54 | 4 before intersection: two per list |
evidence | 54 | 2: documents 5 and 7 |
These are exact operation counts for this corpus, not wall-clock claims. A hash lookup, binary search, compressed decode, cache miss, and sequential text scan do not cost the same number of nanoseconds. The count establishes the source of the advantage: query work depends on the selected lists rather than the whole collection. Later chapters will time complete paths and report distributions.
For a single-term query , write for all indexed term occurrences and for the number of documents containing . The simplified contrast is
Let be the cost of locating in the dictionary. Then
for the scan, while
for the indexed path.
If nearly every document contains , the postings list is long and the gap narrows. If is rare, the index rejects most of the collection without touching it. This is why the distribution of language—not merely collection size—governs search cost.
Four attractive wrong turns
“Just scan faster”
Vectorized substring search, memory mapping, and parallel readers can make a scan excellent. They do not change its dependence on collection size. Scanning is often the right baseline for a tiny collection, a one-time query, or an update-heavy stream whose index would cost more than it saves. It becomes the wrong architecture when many queries repeatedly ask the inverse question.
“Store the vocabulary”
A set of distinct terms can answer whether evidence exists. It cannot say where. The missing information is precisely the postings relation. A dictionary without postings is useful for validation or completion, but it is not a document retrieval index.
“Sort the documents”
Sorting documents by title or by their first term gives one useful order. A document contains many terms, so no single document order places every term's matches together. The index sorts the pairs , allowing one document to participate in many term groups.
“Begin with meaning”
An embedding can place similar texts near one another even when they share no words. That is valuable for a different question. It does not remove the need for exact names, identifiers, quoted phrases, filters, explanations, or a deterministic fallback. Beginning there also hides the simpler baseline against which extra recall and cost must be measured. This book earns semantic retrieval after exact retrieval is understood.
The lesson is not that these techniques are bad. Each answers another question. The design error is adopting one before naming the relation the query needs.
Where the simple index stops
Our handmade index has already smuggled in several decisions:
Indexin a title andindexin a body are, under the rule stated above, different inputs because titles were ignored.searchandsearchesare different terms.- punctuation, accents, compounds, and languages other than English have no rule yet.
- repeated terms lose their frequency.
- word order disappears, so phrases cannot be verified.
- a document ID says nothing about whether the current reader may open it.
None is a cosmetic detail. Index construction and query processing must agree on what a term is, or a query can ask for a key the index could never have written. Authorization has an even harder boundary: inaccessible documents must be removed before ranking, snippets, counts, or timing can reveal them. Those concerns get their own chapters because hiding them inside “tokenize the text” makes a small demo look correct while the real system is not.
Lessons
- A forward collection maps each document to its terms; an inverted index groups the same relation by term and maps each term to its documents.
- The dictionary locates a term's postings list. The postings list records the increasing document IDs that contain the term.
- Pair-sort construction emits document–term pairs, sorts them, and groups equal terms. Its simple form costs comparisons for term occurrences.
- The grouping invariant proves exact membership, uniqueness, and increasing order—properties later query and compression algorithms rely on.
- Exact work counts explain the win before timing does: a query reaches selected postings rather than re-reading the whole collection.
- Scanning, a vocabulary alone, one global document order, and embeddings all answer nearby questions. None substitutes for naming and materializing the term-to-document relation.
Practice
The first machine was actually two
We pretended that spaces reveal terms and lowercase letters make them equal. Real text refuses both assumptions. The constructor might store search while the query produces searches; one side might preserve an accent while the other folds it; a language may not use spaces between words at all.
The next chapter splits the search engine into two machines—one that analyzes documents and one that analyzes queries—and gives them a law: equivalent input must become the same term on both sides. The index is only as truthful as that agreement.
References
- Boswell. “The Life of Samuel Johnson, LL.D..” 1791. — primary public-domain source for the epigraph and its library context
- Manning, Raghavan, Schütze. “Introduction to Information Retrieval.” Cambridge University Press, 2008. — chapters 1, 2, and 4 develop inverted indexes, postings, analysis, and scalable construction
- Zobel and Moffat. “Inverted Files for Text Search Engines.” ACM Computing Surveys, 2006. — comprehensive account of core inverted-file representation, construction, query processing, and extensions