This prompt is for Elasticsearch operators and platform engineers building natural language search interfaces on top of Elasticsearch. It translates a user's unstructured question into a syntactically valid Elasticsearch bool query clause. Use it when you need to bridge the gap between a free-text search bar and a structured filter DSL that vector search alone cannot satisfy. The prompt assumes you have a defined field mapping and that the model receives the available field schema as context. It is not a replacement for a full query engine, but a focused DSL generation step inside a larger retrieval pipeline.
Prompt
Elasticsearch Filter DSL Generation Prompt Template

When to Use This Prompt
Understand the job-to-be-done, the ideal user, required context, and the boundaries where this prompt should not be used.
The ideal user is a search engineer who knows their Elasticsearch field mappings, data types, and query semantics but wants to offload the repetitive work of translating natural language constraints into must, filter, should, and must_not clauses. The prompt requires you to supply a [FIELD_SCHEMA] that describes available fields, their types, and any nested relationships. Without this context, the model will hallucinate field names or produce queries that fail against your index. You should also provide [EXAMPLES] of correct query translations to anchor the model's output style and operator choices.
Do not use this prompt when the user's question requires full-text relevance scoring, vector similarity search, or aggregation logic. This prompt generates filter clauses only—it does not produce match, multi_match, knn, or aggs sections. It is also unsuitable for queries that require cross-index joins, runtime field computation, or script-based filtering. If your retrieval pipeline needs a complete Elasticsearch query body including scoring and pagination, combine this prompt's output with a separate query construction step. For high-risk domains where a bad filter could expose restricted data, always validate the generated DSL against your field schema before execution and consider a human review step for queries that include must_not clauses or nested path traversals.
Use Case Fit
Where this prompt works and where it does not. Use these cards to decide if the Elasticsearch Filter DSL Generation template is the right tool for your retrieval pipeline.
Good Fit: Structured Search Interfaces
Use when: You are building a natural language search bar over an existing Elasticsearch index with well-defined field mappings. The prompt translates user questions into precise bool query clauses. Avoid when: The user's query is purely semantic or conceptual with no clear metadata constraints.
Bad Fit: Unstructured Knowledge Bases
Risk: Using this prompt on a flat, un-mapped document store without defined fields will force the model to hallucinate field names or produce empty filters. Guardrail: Only deploy when you can provide a strict, up-to-date field schema in the prompt context. If no schema exists, use a pure vector search approach instead.
Required Inputs
What to watch: The prompt requires three critical inputs to function: the user's natural language query, a complete field mapping schema (names, types, and valid values), and an output format specification. Guardrail: Implement a pre-flight check that verifies the schema context is present and non-empty before calling the LLM. A missing schema is the most common cause of production failure.
Operational Risk: DSL Syntax Errors
Risk: The generated Elasticsearch DSL may contain invalid JSON, incorrect operator types, or malformed bool clause nesting, causing the search request to be rejected by the cluster. Guardrail: Never send the raw LLM output directly to Elasticsearch. Always validate the JSON structure against a minimal Elasticsearch DSL schema and use a try/catch block with a fallback to a safe match query on failure.
Operational Risk: Field Mapping Drift
Risk: If your index mapping changes, the prompt's hardcoded schema becomes stale, leading to queries against non-existent fields and zero results. Guardrail: Automate the injection of the current index mapping into the prompt context at runtime using the Elasticsearch Get Mapping API. Do not rely on a static, manually updated schema string.
Bad Fit: Complex Nested Queries
Risk: User queries requiring deeply nested bool logic across multiple relation levels or complex nested object queries often exceed the model's reliable generation capability, producing subtly incorrect filters. Guardrail: For advanced nested logic, decompose the user query into simpler sub-queries first, or route to a deterministic query builder. Use the LLM only for top-level filter extraction and simple AND/OR combinations.
Copy-Ready Prompt Template
A reusable prompt template for generating valid Elasticsearch bool query clauses from natural language user questions.
This template is the core instruction set you will copy into your prompt assembly layer. It is designed to accept a user's natural language question, a mapping of available index fields, and a set of constraints, and return a syntactically correct Elasticsearch Query DSL bool query. The prompt uses square-bracket placeholders for all dynamic inputs, ensuring you can wire it directly into a Python, TypeScript, or API-based prompt builder without manual string surgery.
textYou are an expert Elasticsearch Query DSL generator. Your task is to translate a user's natural language question into a valid Elasticsearch `bool` query object. ## INPUT User Question: [USER_QUESTION] ## CONTEXT Available Index Fields and Their Types: [INDEX_MAPPING] ## CONSTRAINTS - Output must be a single, valid JSON object representing a `bool` query. - Use only the fields provided in the index mapping. Do not invent fields. - For full-text search, use a `match` query inside the `must` clause. - For exact value filters (e.g., status, category, tags of type 'keyword'), use a `term` or `terms` query inside the `filter` clause. - For numerical or date ranges, use a `range` query inside the `filter` clause. - If the user's question implies excluding something, use a `must_not` clause. - If the question contains multiple constraints that should all match, place them in `must` or `filter` as appropriate. - If the question contains alternatives, use a `should` clause with `minimum_should_match` set appropriately. - If the question is ambiguous or cannot be translated with the available fields, return a JSON object with a single key "error" and a descriptive message. - Do not include any explanatory text outside the JSON object. ## OUTPUT_SCHEMA { "query": { "bool": { "must": [], "filter": [], "should": [], "must_not": [] } } } ## EXAMPLES User Question: "Find active users in the engineering department" Index Mapping: { "status": { "type": "keyword" }, "department": { "type": "keyword" } } Output: { "query": { "bool": { "filter": [ { "term": { "status": "active" } }, { "term": { "department": "engineering" } } ] } } } User Question: "Show me documents about machine learning or AI from the last 30 days" Index Mapping: { "content": { "type": "text" }, "created_date": { "type": "date" } } Output: { "query": { "bool": { "must": [ { "bool": { "should": [ { "match": { "content": "machine learning" } }, { "match": { "content": "AI" } } ], "minimum_should_match": 1 } } ], "filter": [ { "range": { "created_date": { "gte": "now-30d/d" } } } ] } } }
To adapt this template, replace each square-bracket placeholder with data from your application context. [USER_QUESTION] receives the raw user input. [INDEX_MAPPING] should be a JSON-like summary of your index's field names and types, which is critical for preventing hallucinated fields. For production use, always validate the generated JSON against your actual index mapping and a DSL syntax checker before executing the query. If the model returns an error object, your harness should log it and fall back to a simpler multi_match query or surface the ambiguity to the user.
Prompt Variables
Inputs the prompt needs to work reliably. Validate each before sending the prompt.
| Placeholder | Purpose | Example | Validation Notes |
|---|---|---|---|
[USER_QUERY] | The natural language query containing filter constraints to be translated into Elasticsearch DSL. | Show me critical errors from the payment-service in the last 24 hours. | Must be a non-empty string. Check for injection attempts or shell metacharacters if passed directly from user input. |
[INDEX_MAPPING] | A JSON representation of the target Elasticsearch index mapping, including field names, types, and nested object structures. | {"properties": {"service": {"type": "keyword"}, "@timestamp": {"type": "date"}}} | Must be valid JSON. Parse and verify required fields exist. Reject if mapping is empty or missing key fields referenced in the query. |
[FIELD_DESCRIPTIONS] | A natural language description of what each field represents to aid semantic matching between user terms and index fields. | The 'service' field is the name of the microservice. 'level' is the log severity. | Must be a non-empty string. Ensure descriptions cover fields likely to appear in user queries. Missing descriptions increase hallucination risk. |
[OUTPUT_SCHEMA] | The strict JSON schema the generated Elasticsearch DSL must conform to, typically a bool query object. | {"type": "object", "properties": {"query": {"type": "object"}}, "required": ["query"]} | Must be valid JSON Schema. Validate the generated DSL against this schema programmatically before sending to Elasticsearch. |
[CURRENT_TIME] | An ISO 8601 timestamp representing 'now' for resolving relative time expressions like 'last 24 hours'. | 2024-05-20T14:30:00Z | Must be a valid ISO 8601 string. If null or missing, relative time resolution will fail. Set explicitly to ensure deterministic behavior in tests. |
[NESTED_PATH_CONFIG] | A list of fields that have a 'nested' datatype in the mapping, requiring a nested query wrapper. | ["transactions", "errors.stack_trace"] | Must be an array of strings. Validate that each path exists in the [INDEX_MAPPING] as a nested type. Missing this config causes incorrect DSL for nested objects. |
[EXAMPLES] | A set of few-shot examples mapping user queries to correct Elasticsearch DSL outputs to guide the model's generation. | [{"query": "errors from auth", "dsl": {"bool": {"must": [{"term": {"service": "auth"}}, {"term": {"level": "error"}}]}}}] | Must be an array of valid {query, dsl} objects. Validate each example's DSL against the [OUTPUT_SCHEMA] and [INDEX_MAPPING]. Bad examples poison output. |
Implementation Harness Notes
How to wire the Elasticsearch Filter DSL prompt into a production application with validation, retries, and safe execution.
The Elasticsearch Filter DSL prompt is not a standalone chatbot. It is a component inside a retrieval pipeline that must produce syntactically valid, field-mapped, and safe-to-execute filter clauses. The application layer is responsible for receiving the model's output, validating it against the target index mapping, and deciding whether to execute, repair, or reject the generated DSL. Treat the LLM output as a draft that requires structural verification before it touches your Elasticsearch cluster.
Start by defining a strict output contract. The prompt template should include an [OUTPUT_SCHEMA] placeholder that specifies the expected JSON structure, such as a bool query object with must, filter, should, and must_not clauses. After the model responds, run a multi-stage validation harness: (1) JSON syntax parse with a library like json.loads() and reject on parse failure; (2) schema validation against a JSON Schema or Pydantic model that enforces the Elasticsearch DSL structure, including allowed clause types and operator values; (3) field mapping validation that checks every field name against the actual index mapping retrieved from GET /{index}/_mapping, rejecting unknown fields or suggesting corrections; (4) type coercion checks that verify string values match keyword fields, numeric values match integer/long/float fields, and date strings match the index's date format. If any stage fails, log the failure with the original query, the raw model output, and the specific validation error for debugging.
For retry logic, implement a bounded recovery loop. If validation fails, construct a retry prompt that includes the original user query, the failed DSL output, and the specific validation error message. Use a [RETRY_CONTEXT] placeholder in the prompt template to inject this feedback. Limit retries to a maximum of 2 attempts to avoid infinite loops and escalating latency. If the model cannot produce valid DSL after retries, fall back to a safe default: either execute the query without filters, return an empty filter clause ({"match_all": {}}), or surface the ambiguity to the user with a clarification request. Never execute partially validated or repaired DSL without explicit approval in high-risk contexts such as access-controlled indices or compliance-sensitive data.
Model choice matters for this task. Prefer models with strong JSON generation and instruction-following capabilities, such as GPT-4o, Claude 3.5 Sonnet, or fine-tuned open-weight models that have been trained on structured output tasks. Enable structured output modes or JSON mode where available to reduce syntax errors. For production observability, log every prompt invocation with: the user query, the generated DSL, validation results, retry count, latency, and whether the filter was executed or rejected. This trace data is essential for debugging field mapping drift, model regression after version upgrades, and query patterns that consistently produce invalid DSL.
Finally, implement a human review path for high-risk or novel filter patterns. If the generated DSL includes must_not clauses, nested queries, or script-based filters, consider flagging these for review before execution, especially in multi-tenant systems where a malformed exclusion filter could hide data the user is authorized to see. Pair this prompt with the Structured JSON Filter Output Prompt Template for schema enforcement and the Metadata Constraint Parsing Prompt Template for field-level extraction before DSL assembly. The goal is a defense-in-depth harness where the LLM proposes, the application validates, and the system executes only what passes every structural and semantic check.
Expected Output Contract
The structure, fields, and validation rules for a successful Elasticsearch bool query clause generated from a natural language query.
| Field or Element | Type or Format | Required | Validation Rule |
|---|---|---|---|
query.bool | object | Root object must be a valid Elasticsearch bool query structure. Parse check: JSON.parse() succeeds and matches bool query schema. | |
query.bool.filter | array of objects | Must contain at least one filter clause. Each element must be a valid Elasticsearch query DSL clause (term, terms, range, exists, etc.). Schema check: no empty filter array. | |
query.bool.must_not | array of objects | If present, each element must be a valid exclusion clause. Validation: no double-negation patterns detected. Null allowed if no exclusions extracted. | |
query.bool.minimum_should_match | integer | Required only when should clauses are present. Must be a positive integer. Parse check: integer value, not string. Null allowed when no should clauses exist. | |
[FIELD_NAME] | string | All field names must match the provided [INDEX_MAPPING] schema. Validation: field existence check against mapping. Unknown fields must trigger a retry or human review. | |
[CLAUSE].term.[FIELD] | object with value key | Term queries must use exact values from [NORMALIZED_VALUES]. Validation: value exists in allowed term list or matches extracted entity. No fuzzy matching in term clauses. | |
[CLAUSE].range.[FIELD].gte/lte | ISO 8601 date or number | Range boundaries must match the field type from [INDEX_MAPPING]. Date fields require ISO 8601 format. Number fields require numeric type. Parse check: moment.js or Number() validation. | |
meta.extraction_confidence | object | If [INCLUDE_CONFIDENCE] is true, each filter clause must include a confidence score between 0.0 and 1.0. Validation: float type, range check, null allowed when feature disabled. |
Common Failure Modes
What breaks first when generating Elasticsearch DSL from natural language and how to guard against it.
Hallucinated Field Names
What to watch: The model invents field names that don't exist in your index mapping (e.g., created_date instead of @timestamp). This produces queries that either fail silently or return zero results. Guardrail: Always provide the full index mapping as context and add a post-generation validation step that checks every field reference against the actual mapping before execution.
Incorrect Operator Semantics
What to watch: The model confuses must vs should vs filter clauses, turning optional constraints into required ones or vice versa. A query for 'budget or luxury hotels' becomes a must clause requiring both. Guardrail: Include explicit operator mapping rules in the prompt and run a structural validator that checks clause types against the detected user intent before the query hits production.
Nested Query Path Errors
What to watch: For indexes with nested objects, the model generates flat queries that miss nested documents or uses incorrect nested path wrappers. Multi-condition filters on nested arrays return false positives. Guardrail: Provide the nested field map explicitly and add a linter that verifies every condition on a nested field is wrapped in the correct nested query block with the right path.
Date Math and Timezone Drift
What to watch: The model misinterprets relative expressions like 'last month' or generates date math that resolves incorrectly at query time due to timezone assumptions. now-1M might mean different things depending on execution context. Guardrail: Normalize all relative time expressions to absolute ISO ranges before DSL generation and include the resolved dates in the harness output for human verification.
Text Analysis Mismatch
What to watch: The model generates match queries on keyword fields or term queries on analyzed text fields. This produces empty results because the query type doesn't match how the field was indexed. Guardrail: Include field type metadata (text, keyword, date, numeric) in the prompt context and add a type-check validator that rejects queries with mismatched query-type-to-field-type pairs.
Overly Complex Bool Nesting
What to watch: The model generates deeply nested bool queries with redundant levels or incorrect minimum_should_match parameters that change the effective logic. Complex AND/OR combinations become unreadable and hard to debug. Guardrail: Set a maximum nesting depth in the prompt constraints and add a structural simplifier that flattens redundant bool wrappers before returning the final DSL.
Evaluation Rubric
Run these checks against a golden dataset of user queries and expected DSL outputs before shipping any changes to the prompt or its harness.
| Criterion | Pass Standard | Failure Signal | Test Method |
|---|---|---|---|
DSL Syntax Validity | Output parses as valid JSON and is accepted by the Elasticsearch | Elasticsearch returns a parse error or the JSON is malformed. | Automated: Pipe the generated DSL to |
Field Mapping Accuracy | Every field name in the generated DSL exists in the target index mapping. | A field name is hallucinated or does not match the provided [INDEX_MAPPING] schema. | Automated: Extract all field paths from the output and assert each is a key in the [INDEX_MAPPING] fixture. |
Operator Correctness | The | A 'should' clause is used where a 'must' is required, or a 'must_not' is missing for an exclusion. | Automated: Compare the generated clause type against a pre-labeled intent in the golden dataset. |
Value Type Consistency | Values in | A string value is provided for an integer field in a | Automated: For each clause, assert the JSON type of the value matches the expected type from the mapping fixture. |
Nested Query Handling | Queries on nested object fields are correctly wrapped in a | A query on a nested field is generated without the | Automated: Identify fields from [INDEX_MAPPING] with |
Constraint Completeness | All explicit constraints from [USER_QUERY] are represented as clauses in the output DSL. | A filterable constraint (e.g., 'red shoes') is present in the query but missing from the generated DSL. | Automated: Use an LLM-as-Judge to compare extracted constraints from the golden query against the generated DSL clauses. |
No Extraneous Clauses | The output DSL contains no clauses that are not directly supported by a constraint in [USER_QUERY]. | A | Automated: Assert the number of generated clauses does not exceed the number of labeled constraints in the golden dataset by more than 1. |
Empty Input Handling | When [USER_QUERY] contains no filterable constraints, the output is a valid, empty | The model hallucinates a filter, returns an error, or generates invalid JSON. | Automated: Run a set of queries with no filter intent and assert the output matches the pre-defined fallback structure exactly. |
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Adapt This Prompt
How to adapt
Use the base prompt with a frontier model (GPT-4o, Claude 3.5 Sonnet) and minimal validation. Focus on getting correct DSL structure for simple bool queries first. Skip nested queries and complex field mappings initially.
codeGenerate an Elasticsearch bool query for: [USER_QUERY] Available fields: [FIELD_LIST]
Watch for
- Missing field mapping validation—model may invent field names
- Incorrect operator precedence in compound bool clauses
- Unquoted string values causing syntax errors
- No handling for unknown or ambiguous field references

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us