Elasticsearch Basic Search Queries
Searching is Elasticsearch's core skill. This topic covers the most-used query types — from returning every document to finding exact values and ranges.
How a Search Request Works
You send:
GET /products/_search + query JSON
Elasticsearch:
1. Reads the inverted index
2. Finds matching document IDs
3. Scores each match by relevance
4. Returns top N documents
You receive:
{ "hits": { "total": {...}, "hits": [ ... ] } }
The Search Response Structure
{
"took": 5, <-- milliseconds to run
"hits": {
"total": {
"value": 42 <-- total matching documents
},
"hits": [ <-- actual documents (first 10 by default)
{
"_index": "products",
"_id": "101",
"_score": 1.8, <-- relevance score (higher = better match)
"_source": { ... }
}
]
}
}
Query 1: match_all
Returns every document in the index. Useful for testing and exploring data.
GET /products/_search
{
"query": {
"match_all": {}
}
}
Query 2: match
The standard full-text search query. It analyzes your search text and finds documents where the field contains those words.
GET /products/_search
{
"query": {
"match": {
"name": "wireless keyboard"
}
}
}
This finds documents where the name field contains "wireless" OR "keyboard." Documents with both words score higher.
Query 3: term
Finds documents where a field contains an exact value. Use this on keyword, number, boolean, and date fields — never on text fields.
GET /products/_search
{
"query": {
"term": {
"category": "electronics"
}
}
}
If you use term on a text field, it often returns nothing because the text field is analyzed (lowercased, split into tokens) but term looks for the exact unmodified value.
match vs term — At a Glance
Query: "Wireless Keyboard" match on text field: Elasticsearch analyzes: ["wireless", "keyboard"] Finds any document containing either word ✔ Returns "Best Wireless Keyboard" and "Gaming Keyboard" term on keyword field: Looks for exactly "Wireless Keyboard" ✔ Returns only docs with that exact string ✘ "wireless keyboard" (lowercase) would NOT match
Query 4: terms
Matches documents where a field contains any one of a list of values — like SQL's IN clause.
GET /products/_search
{
"query": {
"terms": {
"category": ["electronics", "accessories", "gadgets"]
}
}
}
Query 5: range
Finds documents where a numeric or date field falls within a range.
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 500,
"lte": 2000
}
}
}
}
| Operator | Meaning |
|---|---|
| gte | Greater than or equal to |
| gt | Greater than |
| lte | Less than or equal to |
| lt | Less than |
Date ranges work the same way:
"range": {
"created_at": {
"gte": "2024-01-01",
"lte": "2024-12-31"
}
}
Query 6: exists
Finds documents where a specific field has any value (is not null and not missing).
GET /products/_search
{
"query": {
"exists": {
"field": "discount_price"
}
}
}
Controlling Result Count and Pagination
By default, search returns 10 documents. Use size and from to control pagination.
GET /products/_search
{
"query": { "match_all": {} },
"size": 20,
"from": 40
}
This returns documents 41 through 60 — page 3 of a 20-per-page result set.
Sorting Results
GET /products/_search
{
"query": { "match_all": {} },
"sort": [
{ "price": "asc" },
{ "name.raw": "asc" }
]
}
Sort by price ascending, then by name alphabetically as a tiebreaker. Note that sorting by name requires the keyword sub-field (name.raw), not the analyzed text field.
Returning Only Specific Fields
GET /products/_search
{
"query": { "match_all": {} },
"_source": ["name", "price", "category"]
}
Elasticsearch returns only those three fields instead of the full document, which reduces network overhead on large documents.
