Conditional execution
In ingest pipelines, you can control whether a processor runs by using the optional if
parameter. This allows for conditional execution of processors based on the incoming document contents. The condition is written as a Painless script and evaluated against the document context (ctx
).
Basic conditional execution
Each processor can include an if
clause. If the condition evaluates to true
, the processor runs; otherwise, it’s skipped.
Example: Drop debug-level logs
The following pipeline drops any document in which the log_level
field is equal to debug
:
PUT _ingest/pipeline/drop_debug_logs
{
"processors": [
{
"drop": {
"if": "ctx.log_level == 'debug'"
}
}
]
}
Example index request
POST logs/_doc/1?pipeline=drop_debug_logs
{
"message": "User logged in",
"log_level": "debug"
}
This document is dropped because the condition evaluates to true
:
{
"_index": "logs",
"_id": "1",
"_version": -3,
"result": "noop",
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
}
}
Null-safe field checks when using nested fields
When working with nested fields, it’s important to avoid null pointer exceptions. Use the null-safe ?.
operator in Painless scripts.
Example: Drop documents based on a nested field
The following drop processor executes only if the nested app.env
field exists and equals debug
:
PUT _ingest/pipeline/drop_debug_env
{
"processors": [
{
"drop": {
"if": "ctx.app?.env == 'debug'"
}
}
]
}
If the null-safe ?.
operator is not configured, indexing any document that doesn’t contain the app.env
field will trigger the following null pointer exception:
{
"error": "IngestProcessorException[ScriptException[runtime error]; nested: NullPointerException[Cannot invoke \"Object.getClass()\" because \"callArgs[0]\" is null];]",
"status": 400
}
Handling flattened fields
If your document has a flattened field, for example, "app.env": "debug"
, use the dot_expander
processor to convert it into a nested structure:
PUT _ingest/pipeline/drop_debug_env
{
"processors": [
{
"dot_expander": {
"field": "app.env"
}
},
{
"drop": {
"if": "ctx.app?.env == 'debug'"
}
}
]
}
Safe method calls in conditions
Avoid calling methods on potential null values. Use constants or null checks instead:
{
"drop": {
"if": "ctx.app?.env != null && ctx.app.env.contains('debug')"
}
}
Full example: Multi-step conditional pipeline
The following ingest pipeline uses three processors:
set
: If no value is provided in theuser
field, sets theuser
field toguest
.set
: If thestatus_code
is provided and is higher than400
, sets theerror
field totrue
.drop
: If theapp.env
field is equal todebug
, drops the entire document.
PUT _ingest/pipeline/logs_processing
{
"processors": [
{
"set": {
"field": "user",
"value": "guest",
"if": "ctx.user == null"
}
},
{
"set": {
"field": "error",
"value": true,
"if": "ctx.status_code != null && ctx.status_code >= 400"
}
},
{
"drop": {
"if": "ctx.app?.env == 'debug'"
}
}
]
}
Simulate the pipeline
The following simulation request applies the conditional logic to three documents:
POST _ingest/pipeline/logs_processing/_simulate
{
"docs": [
{
"_source": {
"message": "Successful login",
"status_code": 200
}
},
{
"_source": {
"message": "Database error",
"status_code": 500,
"user": "alice"
}
},
{
"_source": {
"message": "Debug mode trace",
"app": { "env": "debug" }
}
}
]
}
The response demonstrates how the processors respond based on each condition:
{
"docs": [
{
"doc": {
"_index": "_index",
"_id": "_id",
"_source": {
"status_code": 200,
"message": "Successful login",
"user": "guest"
},
"_ingest": {
"timestamp": "2025-04-16T14:04:35.923159885Z"
}
}
},
{
"doc": {
"_index": "_index",
"_id": "_id",
"_source": {
"status_code": 500,
"message": "Database error",
"error": true,
"user": "alice"
},
"_ingest": {
"timestamp": "2025-04-16T14:04:35.923198551Z"
}
}
},
null
]
}