Inferensys

Prompt

Elasticsearch Filter DSL Generation Prompt Template

A practical prompt playbook for using the Elasticsearch Filter DSL Generation Prompt Template in production AI workflows. Generates valid Elasticsearch bool query clauses from user questions, with eval for DSL syntax correctness, field mapping validation, and nested query handling.
Stylish WeWork-like workspace with hot desks and document wall, professional searching through enterprise knowledge base on a mounted ultrawide display, warm industrial pendants overhead.
PROMPT PLAYBOOK

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.

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.

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.

PRACTICAL GUARDRAILS

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.

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.

PROMPT PLAYBOOK

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.

text
You 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.

IMPLEMENTATION TABLE

Prompt Variables

Inputs the prompt needs to work reliably. Validate each before sending the prompt.

PlaceholderPurposeExampleValidation 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.

PROMPT PLAYBOOK

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.

IMPLEMENTATION TABLE

Expected Output Contract

The structure, fields, and validation rules for a successful Elasticsearch bool query clause generated from a natural language query.

Field or ElementType or FormatRequiredValidation 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.

PRACTICAL GUARDRAILS

Common Failure Modes

What breaks first when generating Elasticsearch DSL from natural language and how to guard against it.

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.

IMPLEMENTATION TABLE

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.

CriterionPass StandardFailure SignalTest Method

DSL Syntax Validity

Output parses as valid JSON and is accepted by the Elasticsearch _validate/query API without errors.

Elasticsearch returns a parse error or the JSON is malformed.

Automated: Pipe the generated DSL to _validate/query?explain=false and assert valid: true.

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 bool clause structure (must, filter, should, must_not) correctly reflects the user's AND/OR/NOT intent from [USER_QUERY].

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 term, range, and match clauses match the data type of the field as defined in [INDEX_MAPPING].

A string value is provided for an integer field in a range query, or a number is used in a term query on a text field.

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 nested query block with a valid path.

A query on a nested field is generated without the nested wrapper, or the path is incorrect.

Automated: Identify fields from [INDEX_MAPPING] with type: nested and assert the output contains a corresponding nested query.

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 match_all clause is added when a specific filter is requested, or an unrelated filter is invented.

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 bool query or a match_all as defined by [FALLBACK_STRATEGY].

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.

ADAPTATION OPTIONS

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.

code
Generate 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
Prasad Kumkar

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.