Capstone — Building a Real Search & Analytics Feature
Elasticsearch / OpenSearch
Chapter 11 · Capstone: Building a Real Search & Analytics Feature
Ten chapters covered what makes this engine genuinely different, closing two real loops (postgres1-6's own deferred search comparison, and its own faceted-search callout) along the way. This capstone builds one real, working product search feature — but only after confirming, using search1-10's own framework, that building it here is actually justified.
The Scenario
An e-commerce company with a genuinely large product catalog is deciding whether to build a dedicated product search feature. Applying search1-10's own five-question framework directly: search is the storefront's own primary feature, not a secondary convenience (question 1 → yes); the catalog is genuinely large enough to benefit from real horizontal distribution (question 2 → yes); faceted filtering (category, brand, price) is a first-class, heavily-used requirement for this storefront (question 3 → yes); relevance quality genuinely affects conversion and revenue (question 4 → yes); and the team is prepared to operate a separate system and keep it synced with the real product database (question 5 → assumed yes). Unlike search1-10's own two exercise scenarios — both genuine "no" cases — this is a real, complete "yes" case, closing that chapter's own framework from the other direction.
The Mapping
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
"description": { "type": "text" },
"category": { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
"brand": { "type": "text", "fields": { "keyword": { "type": "keyword" } } },
"price": { "type": "float" }
}
}
}
This mapping is explicit and deliberate, not left to dynamic inference — avoiding both search1-3's own dynamic-mapping gotcha and search1-7's own analyzed-field aggregation gotcha directly, by giving category and brand a keyword sub-field specifically for exact filtering and aggregation, alongside their own analyzed text version for full-text search.
The Combined Query
POST /products/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "wireless mouse",
"fields": ["name^3", "description"]
}
}
],
"filter": [
{ "term": { "category.keyword": "Electronics" } },
{ "term": { "brand.keyword": "Logitech" } },
{ "range": { "price": { "gte": 10, "lte": 60 } } }
]
}
},
"aggs": {
"by_category": { "terms": { "field": "category.keyword" } },
"by_brand": { "terms": { "field": "brand.keyword" } },
"price_ranges": {
"range": {
"field": "price",
"ranges": [ { "to": 25 }, { "from": 25, "to": 50 }, { "from": 50 } ]
}
}
}
}
name^3 boosts matches in the product name three times higher than matches in the description — search1-6's own boosting material, applied for real. The must clause drives relevance-ranked results; the filter clauses narrow by exact, non-scoring criteria against the keyword sub-fields; the aggs block computes category, brand, and price-range facet counts over that same filtered result set, in the same single request.
Why This Works — Tracing the Mechanism
The ranked results come from BM25 scoring (search1-6) computed via the inverted index (search1-4). The facet counts come from aggregations (search1-7) computed in parallel across shards (search1-8). The whole request executes as fast as it does specifically because of the distributed, parallel architecture search1-8 covered — every piece of this capstone traces back to a specific, real mechanism this course actually explained, not just a feature list.
Chapter Attribution
| Capstone element | Chapter |
|---|---|
| Confirming a dedicated engine is justified for this use case | search1-10 |
| Explicit mapping, keyword sub-fields avoiding two prior gotchas | search1-3, search1-7 |
| multi_match, bool query with must/filter | search1-5 |
| Field boosting (name^3) | search1-6 |
| Nested terms/range aggregations for facets | search1-7 |
| Parallel execution across shards making it fast at scale | search1-8 |
| Underlying inverted index and BM25 scoring mechanism | search1-4, search1-6 |
search1-1's own warn-box named this as real, necessary, ongoing engineering work, and it remains a genuinely separate project of its own, out of scope here. It also doesn't build autocomplete/suggest functionality, typo-tolerance/fuzzy-matching tuning, or a real cluster deployment/production-hardening walkthrough — search1-8's own sharding/replication material stayed conceptual throughout this course. This capstone demonstrates exactly what search1-10's own framework confirmed was justified for this specific scenario — not a claim that every possible feature of a production search system is "done."
search1-1 opened this course by naming the inverted index and relevance scoring as this engine's own primary, founding design center — not a bolt-on feature. This capstone is the proof: one real request, genuinely combining search, filtering, relevance, and analytics, built entirely on the mechanisms this course actually explained.
Hands-On Exercises
Walk through this chapter's own application of search1-10's five-question framework to the e-commerce scenario, and explain why this capstone represents a genuine "yes" case, complementing search1-10's own two "no" exercise scenarios.
📄 View solutionExplain why the capstone's own mapping gives category and brand a keyword sub-field, tying your answer to both search1-3's dynamic-mapping gotcha and search1-7's analyzed-field aggregation gotcha, with a concrete example of what would go wrong without it.
📄 View solutionUsing this chapter's own "Why This Works" section, trace the combined query's own results back to the specific underlying mechanisms (inverted index, BM25, sharding) covered earlier in this course.
📄 View solutionChapter 11 Quick Reference — Course Complete
- search1-10's own framework applied first, confirming a dedicated engine is genuinely justified for this scenario — a real "yes" case
- Explicit mapping with keyword sub-fields deliberately avoids search1-3's and search1-7's own gotchas
- One combined request: relevance-ranked, boosted, faceted, and filtered — search1-5/6/7 working together
- Fast at scale because of search1-8's own distributed, parallel shard execution
- Honest scope note: no real data-sync pipeline, no autocomplete, no fuzzy matching, no production deployment walkthrough
- This closes the full 11-chapter Elasticsearch/OpenSearch course, and the entire Databases subject's own bucket list