Querying — Query DSL vs. SQL
Elasticsearch / OpenSearch
Chapter 5 · Querying — Query DSL vs. SQL
search1-3's own basic _search?q=... query was just a preview. This chapter covers the real query language — a genuinely different paradigm from SQL, not just different syntax for the same idea.
A Genuinely Different Query Paradigm
SQL (per mysql2/mysql3/postgres1) is a declarative, text-based language with its own dedicated syntax. The Query DSL is expressed as ordinary JSON, sent as the body of an HTTP POST request to a _search endpoint — not a special language at all, just structured data describing what to search for, sent over the exact same REST API search1-3 already introduced.
match vs. term — The Most Important Distinction
A match query analyzes the search input the same way the field was analyzed at index time (search1-4's own analyzer material) — meant for genuine full-text search against analyzed text fields. Searching "quick fox" can match a document containing "The Quick Brown Fox", because both go through identical lowercasing and tokenization.
A term query does not analyze the input at all — it looks for an exact match against the raw indexed term, meant for exact-value fields (an ID, a status enum, a keyword-mapped field). This is probably the single most important practical query-writing gotcha in the entire engine: using term against an analyzed text field routinely returns zero results, because the raw, unanalyzed search string doesn't match any of the lowercased, tokenized terms actually stored in the inverted index.
bool Queries — Combining Conditions
A bool query combines multiple conditions using must, should, must_not, and filter clauses — roughly analogous in spirit to SQL's own AND/OR/NOT, but structurally very different (nested JSON objects rather than infix operators).
The must-vs-filter distinction specifically has no direct SQL equivalent: must clauses contribute to relevance scoring (search1-6's own material); filter clauses express yes/no criteria that don't affect scoring at all — and, as a result, are more cacheable and efficient. Ordinary SQL's own WHERE clause has no built-in concept of "this condition should also feed a relevance score" at all — this distinction is genuinely new territory.
A Worked Example
POST /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "description": "wireless mouse" } }
],
"filter": [
{ "range": { "price": { "lte": 50 } } },
{ "term": { "category": "electronics" } }
]
}
}
}
The match clause does real, relevance-affecting full-text search; the filter clauses narrow the results by exact, non-scoring criteria (price range, category) — a realistic e-commerce-style query, directly previewing search1-11's own capstone.
Comparing the Two Paradigms Side by Side
| SQL | Query DSL | |
|---|---|---|
| Surface form | Text, dedicated syntax | JSON, sent as an HTTP request body |
| Combining conditions | Infix AND/OR/NOT | Nested must/should/must_not/filter |
| Execution model | Query planner optimizing a relational plan | Directly invokes the engine's own search/scoring machinery |
term query for "Quick Fox" against a text field will typically return zero results, since the inverted index actually stores lowercased, tokenized terms like quick and fox, not the raw string "Quick Fox". The exact same search, run as a match query instead, works correctly — because match analyzes the input identically to how the field was analyzed at index time, per this chapter's own earlier explanation.
search1-6's own relevance-scoring chapter builds on next.
Hands-On Exercises
Explain the difference between a match query and a term query, and explain the classic beginner mistake of using term against an analyzed text field, using a concrete before/after example.
📄 View solutionExplain the difference between must and filter clauses inside a bool query — specifically, what does "contributes to relevance scoring" actually mean, and why does SQL's own WHERE clause have no direct equivalent to this distinction?
📄 View solutionUsing this chapter's own worked example, explain why combining a match clause and a filter clause in the same bool query is a genuinely common, realistic pattern — what real-world scenario does each clause serve?
📄 View solutionChapter 5 Quick Reference
- Query DSL — JSON in an HTTP POST body, not a text-based dedicated language like SQL
- match — analyzed, for full-text search · term — exact, unanalyzed, the classic beginner trap against text fields
- bool — must/should/must_not/filter, nested JSON rather than infix operators
- must — affects relevance score · filter — yes/no, non-scoring, more cacheable — no direct SQL WHERE equivalent
- SQL uses a query-planner-optimized relational plan; Query DSL directly invokes the engine's own search/scoring machinery
- Next chapter: Relevance Scoring & Full-Text Search Done Right