How to Use Elasticsearch Query

How to Use Elasticsearch Query Elasticsearch is a powerful, distributed search and analytics engine built on Apache Lucene. It enables real-time search and analysis of large volumes of data with exceptional speed and scalability. At the heart of Elasticsearch’s functionality lies its query system — a sophisticated, flexible mechanism that allows users to retrieve, filter, aggregate, and rank data

Nov 10, 2025 - 12:12
Nov 10, 2025 - 12:12
 2

How to Use Elasticsearch Query

Elasticsearch is a powerful, distributed search and analytics engine built on Apache Lucene. It enables real-time search and analysis of large volumes of data with exceptional speed and scalability. At the heart of Elasticsearchs functionality lies its query system a sophisticated, flexible mechanism that allows users to retrieve, filter, aggregate, and rank data with precision. Whether youre building a product search engine, analyzing log data, or powering real-time dashboards, mastering how to use Elasticsearch query is essential for unlocking the full potential of the platform.

Unlike traditional relational databases that rely on SQL for structured queries, Elasticsearch uses a JSON-based query language that supports full-text search, structured filtering, geospatial queries, aggregations, and more. This flexibility makes it ideal for modern applications where data is unstructured, semi-structured, or rapidly evolving. Understanding how to construct effective queries from simple term matches to complex boolean combinations and nested aggregations is the key to delivering fast, accurate, and relevant results to end users.

This guide provides a comprehensive, step-by-step walkthrough of how to use Elasticsearch query effectively. Youll learn practical techniques, industry best practices, real-world examples, and the tools that can help you debug and optimize your queries. By the end of this tutorial, youll be equipped to write efficient, scalable, and maintainable Elasticsearch queries that meet the demands of production environments.

Step-by-Step Guide

Setting Up Elasticsearch

Before you can begin writing queries, you need a running Elasticsearch instance. Elasticsearch can be deployed locally for development or in the cloud for production use. The easiest way to get started is by using Docker.

Run the following command in your terminal to start Elasticsearch version 8.x:

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:8.12.0

Once the container is running, verify the installation by visiting http://localhost:9200 in your browser. You should see a JSON response containing cluster information, including the version number and cluster name.

For development, you may also use Elastic Cloud (SaaS) or local installations via ZIP or TAR packages available on the official Elasticsearch website. Ensure that your Java Runtime Environment (JRE) meets the minimum version requirements Elasticsearch 8.x requires Java 17 or higher.

Understanding the Query DSL

Elasticsearch uses a JSON-based Query DSL (Domain Specific Language) to define search requests. Unlike SQL, which is declarative and table-oriented, the Query DSL is hierarchical and document-oriented. Every request to Elasticsearch is a JSON object containing one or more query components.

The two most fundamental types of queries are:

  • Leaf queries operate on a single field (e.g., term, match, range)
  • Compound queries combine multiple leaf or compound queries (e.g., bool, dis_max)

A basic query structure looks like this:

{

"query": {

"match": {

"title": "elasticsearch tutorial"

}

}

}

This query searches for documents where the title field contains the words elasticsearch or tutorial. The match query analyzes the input text and performs a full-text search across the field.

Performing a Simple Match Query

The match query is the most commonly used query type for full-text search. It breaks down the input text into tokens using an analyzer (default: standard analyzer), then searches for documents containing any of those tokens.

Example: Search for products with wireless headphones in the description.

POST /products/_search

{

"query": {

"match": {

"description": "wireless headphones"

}

}

}

By default, match uses OR logic a document will be returned if it contains either wireless or headphones. To require all terms, use the operator parameter:

{

"query": {

"match": {

"description": {

"query": "wireless headphones",

"operator": "and"

}

}

}

}

This returns only documents containing both terms.

Using Term Queries for Exact Matching

When you need exact matches such as searching for IDs, statuses, or keywords that should not be analyzed use the term query.

Example: Find all orders with status shipped.

POST /orders/_search

{

"query": {

"term": {

"status": "shipped"

}

}

}

Important: term queries do not analyze the input. If your field is analyzed (e.g., a text field), you must use the .keyword sub-field for exact matching:

{

"query": {

"term": {

"category.keyword": "Electronics"

}

}

}

This is because text fields are tokenized during indexing, while keyword fields are stored as-is. Always use .keyword for exact matches on text fields.

Filtering with Range Queries

Range queries allow you to find documents within a specific numeric, date, or geographic range.

Example: Find products priced between $50 and $200.

POST /products/_search

{

"query": {

"range": {

"price": {

"gte": 50,

"lte": 200

}

}

}

}

Supported operators:

  • gt greater than
  • gte greater than or equal
  • lt less than
  • lte less than or equal

For dates, use ISO 8601 format:

{

"query": {

"range": {

"created_at": {

"gte": "2024-01-01T00:00:00Z",

"lt": "2024-02-01T00:00:00Z"

}

}

}

}

Combining Queries with Bool Query

The bool query is the most powerful compound query in Elasticsearch. It allows you to combine multiple queries using logical operators: must, should, must_not, and filter.

Example: Find products in Electronics category, priced between $100$500, and not discontinued.

POST /products/_search

{

"query": {

"bool": {

"must": [

{

"term": {

"category.keyword": "Electronics"

}

},

{

"range": {

"price": {

"gte": 100,

"lte": 500

}

}

}

],

"must_not": [

{

"term": {

"status": "discontinued"

}

}

]

}

}

}

must all conditions must be true (AND logic)

should at least one condition must be true (OR logic)

must_not exclude documents matching this condition

filter same as must, but does not calculate relevance scores (more efficient)

Use filter for conditions that dont affect scoring such as status, category, or date ranges to improve performance.

Searching Across Multiple Fields

When you need to search across multiple fields (e.g., title, description, tags), use multi_match.

Example: Search for wireless headphones in title, description, and tags.

POST /products/_search

{

"query": {

"multi_match": {

"query": "wireless headphones",

"fields": ["title", "description", "tags"]

}

}

}

You can also specify the type of matching:

  • best_fields default; scores documents based on the best matching field
  • most_fields combines scores from all fields (useful for faceted search)
  • cross_fields treats all fields as one, useful for multi-word queries across fields
  • phrase requires exact phrase match
  • phrase_prefix matches phrases with prefix on the last term

Example using cross_fields:

{

"query": {

"multi_match": {

"query": "wireless headphones",

"fields": ["title", "description"],

"type": "cross_fields",

"operator": "and"

}

}

}

Using Wildcards and Regex Queries

For partial matching, Elasticsearch supports wildcard and regex queries. However, these are slower than term or match queries and should be used sparingly.

Wildcard example: Find products whose SKU starts with ABC.

POST /products/_search

{

"query": {

"wildcard": {

"sku.keyword": "ABC*"

}

}

}

Regex example: Find SKUs ending in -PRO.

{

"query": {

"regexp": {

"sku.keyword": ".*-PRO$"

}

}

}

Warning: Regex and wildcard queries can be resource-intensive, especially on large datasets. Always use them on keyword fields and consider using n-gram tokenization for better performance.

Sorting and Pagination

By default, Elasticsearch sorts results by relevance score (_score). You can override this behavior using the sort parameter.

Example: Sort products by price ascending, then by name descending.

POST /products/_search

{

"query": {

"match_all": {}

},

"sort": [

{

"price": {

"order": "asc"

}

},

{

"name.keyword": {

"order": "desc"

}

}

]

}

For pagination, use from and size:

{

"query": {

"match_all": {}

},

"from": 20,

"size": 10

}

This retrieves results 2130. For deep pagination (>10,000 results), use search_after or scroll for better performance.

Aggregations for Data Analysis

Aggregations allow you to group and summarize data similar to SQLs GROUP BY and aggregate functions.

Example: Get the count of products by category and average price per category.

POST /products/_search

{

"size": 0,

"aggs": {

"categories": {

"terms": {

"field": "category.keyword",

"size": 10

},

"aggs": {

"avg_price": {

"avg": {

"field": "price"

}

}

}

}

}

}

The size: 0 suppresses document hits you only want the aggregation results.

Other useful aggregations:

  • date_histogram group by time intervals (daily, monthly)
  • stats returns min, max, avg, sum, count
  • percentiles calculate percentiles (e.g., 95th percentile response time)
  • cardinality count unique values (e.g., unique users)

Highlighting Search Results

Highlighting helps users see where their search terms appear in the results.

Example: Highlight matches in the description field.

POST /products/_search

{

"query": {

"match": {

"description": "wireless headphones"

}

},

"highlight": {

"fields": {

"description": {}

}

}

}

The response includes a highlight section with snippets containing <em> tags around matched terms. You can customize the tags, fragment size, and number of fragments:

{

"highlight": {

"fields": {

"description": {

"fragment_size": 150,

"number_of_fragments": 3,

"pre_tags": [""],

"post_tags": [""]

}

}

}

}

Using Index Patterns and Aliases

In production, you often work with time-series data (e.g., logs, metrics). Instead of querying individual indices like logs-2024-05-01, use index patterns or aliases.

Create an alias:

POST /_aliases

{

"actions": [

{

"add": {

"index": "logs-2024-05-01",

"alias": "logs-current"

}

}

]

}

Now query the alias:

POST /logs-current/_search

{

"query": {

"match": {

"message": "error"

}

}

}

Index patterns allow you to search across multiple indices using wildcards:

POST /logs-2024-*/_search

This approach simplifies maintenance and enables seamless rollover strategies.

Best Practices

Use Keyword Fields for Exact Matches

Always use the .keyword sub-field when performing exact matches, filters, or aggregations on text fields. Text fields are analyzed and tokenized, making them unsuitable for precise comparisons. The .keyword field stores the raw value and supports exact matching, sorting, and aggregations.

Prefer Filter Context Over Query Context

When a condition is used for filtering (e.g., status, category, date range), place it in the filter clause of a bool query. Filters are cached and do not compute relevance scores, resulting in significantly faster performance.

Bad:

"must": [

{ "range": { "price": { "gte": 100 } } }

]

Good:

"filter": [

{ "range": { "price": { "gte": 100 } } }

]

Limit Results with Size and Use Search After for Deep Pagination

Never use from and size for pagination beyond 10,000 results. Elasticsearch has a default limit of 10,000 for from + size due to performance concerns.

Use search_after for deep pagination:

POST /products/_search

{

"size": 10,

"query": {

"match_all": {}

},

"sort": [

{ "price": "asc" },

{ "_id": "asc" }

],

"search_after": [150, "abc123"]

}

Pass the sort values of the last result from the previous page as search_after. This method is stateless and scales efficiently.

Optimize Analyzers for Your Use Case

Default analyzers may not suit your data. For product search, consider using the standard analyzer with stop words removed. For multilingual content, use the language analyzer (e.g., english, german). For autocomplete, use n-gram or edge-n-gram tokenizers.

Example: Custom analyzer for product names with edge-n-gram for prefix matching.

"analysis": {

"analyzer": {

"product_name_analyzer": {

"type": "custom",

"tokenizer": "edge_ngram",

"filter": ["lowercase"]

}

},

"tokenizer": {

"edge_ngram": {

"type": "edge_ngram",

"min_gram": 1,

"max_gram": 20

}

}

}

Use Index Templates for Consistent Mapping

Define index templates to enforce consistent field mappings across time-series indices. This ensures that new indices inherit the correct data types, analyzers, and settings.

Example template for log data:

PUT _index_template/logs_template

{

"index_patterns": ["logs-*"],

"template": {

"settings": {

"number_of_shards": 3,

"number_of_replicas": 1

},

"mappings": {

"properties": {

"timestamp": { "type": "date" },

"level": { "type": "keyword" },

"message": { "type": "text", "analyzer": "standard" }

}

}

}

}

Monitor Query Performance with Profile API

Use the profile parameter to analyze how your query is executed and identify bottlenecks.

POST /products/_search

{

"profile": true,

"query": {

"match": {

"description": "wireless headphones"

}

}

}

The response includes detailed timing information per shard, including time spent in tokenization, scoring, and filtering. Use this to optimize slow queries.

Avoid Wildcards and Regex on Large Datasets

Wildcard (*) and regex queries are expensive because they require scanning all terms in the inverted index. Instead, use n-gram tokenization during indexing or pre-process your data to generate prefix variants.

Use Index Sorting for Frequently Sorted Queries

If you frequently sort by a field (e.g., price, date), enable index sorting during index creation. This stores documents in sorted order on disk, making sort operations much faster.

PUT /products

{

"settings": {

"index.sort.field": "price",

"index.sort.order": "asc"

},

"mappings": {

"properties": {

"price": { "type": "float" }

}

}

}

Regularly Optimize Indices

After bulk indexing or large deletions, run the _forcemerge API to reduce segment count and improve search performance:

POST /products/_forcemerge?max_num_segments=1

Use this sparingly in production its I/O intensive and should be scheduled during off-peak hours.

Tools and Resources

Elasticsearch Head

Elasticsearch Head is a web-based interface for exploring and interacting with your cluster. It provides a visual representation of indices, documents, and query results. While not officially maintained, it remains popular for development.

Install via npm:

npm install -g elasticsearch-head

Then run:

head -p 9100

Access at http://localhost:9100.

Kibana

Kibana is the official visualization and exploration tool for Elasticsearch. It includes a Dev Tools console where you can write, test, and debug queries with syntax highlighting, autocomplete, and response formatting.

Features:

  • Query Console with JSON validation
  • Visualizations: bar charts, pie charts, heatmaps
  • Dashboard creation
  • Index pattern management

Install Kibana alongside Elasticsearch and access it at http://localhost:5601.

Postman or curl

For API testing and automation, use Postman or command-line curl to send HTTP requests to Elasticsearch.

Example curl command:

curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'

{

"query": {

"match": {

"title": "laptop"

}

}

}'

Elasticsearch SQL

If youre more comfortable with SQL, Elasticsearch supports SQL queries via the SQL REST API or Kibanas SQL tab.

POST /_sql?format=txt

{

"query": "SELECT * FROM products WHERE price > 100 AND category = 'Electronics'"

}

Useful for teams transitioning from relational databases, but note that not all SQL features are supported.

OpenSearch Dashboards (Alternative)

OpenSearch is an open-source fork of Elasticsearch and Kibana. If you prefer a fully open-source stack, OpenSearch Dashboards offers similar functionality with a compatible query language.

Documentation and Community

Monitoring and Logging Tools

Use Elasticsearchs built-in monitoring features or integrate with Prometheus and Grafana for real-time cluster metrics. Log your queries in a separate index for audit and performance analysis.

Real Examples

Example 1: E-Commerce Product Search

Scenario: A user searches for red wireless headphones under $150.

Goal: Return products matching the term red wireless headphones, priced under $150, sorted by relevance, with highlights and category aggregations.

POST /products/_search

{

"query": {

"bool": {

"must": [

{

"multi_match": {

"query": "red wireless headphones",

"fields": ["title^3", "description^2", "tags"],

"type": "best_fields",

"operator": "and"

}

}

],

"filter": [

{

"range": {

"price": {

"lt": 150

}

}

},

{

"term": {

"in_stock": true

}

}

]

}

},

"highlight": {

"fields": {

"title": {},

"description": {}

}

},

"aggs": {

"categories": {

"terms": {

"field": "category.keyword",

"size": 5

}

}

},

"sort": [

{

"_score": {

"order": "desc"

}

}

],

"size": 10

}

Key features:

  • Boosted title field for higher relevance
  • Filter for price and availability (cached)
  • Highlights in title and description
  • Category aggregation for faceted navigation

Example 2: Log Analysis for Error Monitoring

Scenario: Find all ERROR-level logs from the last 24 hours, grouped by service and top 10 error messages.

POST /logs-2024-*/_search

{

"size": 0,

"query": {

"bool": {

"must": [

{

"term": {

"level.keyword": "ERROR"

}

}

],

"filter": [

{

"range": {

"timestamp": {

"gte": "now-24h"

}

}

}

]

}

},

"aggs": {

"services": {

"terms": {

"field": "service.keyword",

"size": 10

},

"aggs": {

"error_messages": {

"terms": {

"field": "message.keyword",

"size": 10

}

}

}

},

"errors_per_hour": {

"date_histogram": {

"field": "timestamp",

"calendar_interval": "hour"

}

}

}

}

Result: A breakdown of which services are failing most frequently and the most common error messages, plus a time-series chart of error frequency.

Example 3: Autocomplete with Suggesters

Scenario: Implement a live search autocomplete for product names.

Use the suggest API with completion type.

First, define the mapping:

PUT /products

{

"mappings": {

"properties": {

"name_suggest": {

"type": "completion"

}

}

}

}

Index data with suggestions:

POST /products/_doc/1

{

"name": "Apple AirPods Pro",

"name_suggest": {

"input": ["Apple AirPods Pro", "AirPods Pro", "Apple"],

"weight": 10

}

}

Query for suggestions:

POST /products/_search

{

"size": 0,

"suggest": {

"product-suggest": {

"prefix": "Apple Ai",

"completion": {

"field": "name_suggest",

"size": 5

}

}

}

}

Response returns top 5 matching suggestions with high relevance.

FAQs

What is the difference between match and term queries?

The match query analyzes the input text and searches for tokens across the field ideal for full-text search. The term query looks for exact matches and does not analyze the input ideal for IDs, keywords, or filtered fields. Always use term on .keyword fields for text data.

Why is my Elasticsearch query slow?

Slow queries are often caused by:

  • Using wildcard or regex on large datasets
  • Not using filters for non-scoring conditions
  • Deep pagination with large from values
  • Unoptimized analyzers or mappings
  • High segment count due to frequent indexing

Use the profile API and Kibanas Profiler to identify bottlenecks.

Can I use SQL with Elasticsearch?

Yes, Elasticsearch supports SQL queries via the SQL REST API or Kibanas SQL interface. However, its a translation layer not all SQL features are supported, and performance may not match native Query DSL.

How do I handle case-insensitive searches?

Use the keyword field with a lowercase filter in your analyzer, or use match queries they are case-insensitive by default because they use the same analyzer used during indexing.

Whats the maximum number of results Elasticsearch can return?

By default, Elasticsearch limits from + size to 10,000. To retrieve more, use search_after or scroll. For large exports, consider using the Scroll API or the newer Point-in-Time (PIT) feature.

How do I update documents in Elasticsearch?

Elasticsearch does not update documents in place. Instead, you must reindex the document with the same ID. Use the _update API for partial updates:

POST /products/_update/1

{

"doc": {

"price": 120

}

}

How do I delete documents matching a query?

Use the Delete By Query API:

POST /products/_delete_by_query

{

"query": {

"term": {

"status": "discontinued"

}

}

}

Warning: This is a blocking operation. Use with caution in production.

Conclusion

Mastering how to use Elasticsearch query is not just about learning syntax its about understanding how data is indexed, stored, and retrieved in a distributed, document-oriented system. From simple term matches to complex aggregations and real-time analytics, Elasticsearch provides the tools to build powerful search experiences that scale with your data.

This guide has walked you through the fundamentals of constructing queries, optimizing performance, and applying best practices in real-world scenarios. Youve seen how to combine filters and queries for speed, how to use aggregations for insights, and how to leverage tools like Kibana and the Profile API for debugging.

As you continue to work with Elasticsearch, remember that performance and accuracy are deeply tied to your index design. Invest time in mapping, analyzer configuration, and index templates they pay off exponentially in query efficiency.

Whether youre building a product catalog, monitoring system logs, or analyzing user behavior, the ability to write precise, efficient Elasticsearch queries is a critical skill. Use this guide as a reference, experiment with real data, and gradually expand your knowledge into advanced topics like scripting, percolation, and machine learning integrations.

Elasticsearch is not just a search engine its a platform for turning raw data into actionable intelligence. With the techniques outlined here, youre now equipped to unlock its full potential.