You're viewing version 3.0 of the OpenSearch documentation. This version is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.
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 theuserfield, sets theuserfield toguest.set: If thestatus_codeis provided and is higher than400, sets theerrorfield totrue.drop: If theapp.envfield 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
]
}