You are designing the simplest thing that could possibly work as a search engine: a client sends a JSON query, the engine returns documents that match — ranked by relevance — in under 100 ms across a corpus that does not fit on one machine. Five million books, a search box, and a query that says "distributed systems."
The naive plan is SELECT * FROM books WHERE body LIKE '%distributed systems%'. It is wrong before you even count the rows. LIKE '%…%' is unanchored, so no B-tree applies; throwing 64 cores at it cuts wall-clock by 64× and still does not approach 100 ms; and there is no concept of relevance in the answer. The architectural response is not faster hardware. It is to flip the relation between document and term and serve queries from a precomputed map.
That map is an inverted index: each word in your corpus points to the list of document IDs that contain it. A search becomes a hash lookup followed by a sorted-list intersection — the cost collapses from O(documents) to O(matches). Every later mechanism — segments, refresh/flush, shards, replicas, scatter-gather, BM25 — exists to make that one structure correct under mutability, durability, and scale.
Resist the urge to "describe Elasticsearch." Make decisions yourself, defend them, and let the design push back. The point is to feel why each price is paid: why segments are immutable, why num_primary_shards is fixed for life, why replicas help reads and not writes, why deep pagination has a hard wall at 10 000, why BM25 is approximate across shards.