Skip to content

Commit 72da17c

Browse files
limotovajoegallo
andauthored
Add option for Append Processor to skip/allow empty values (#105718)
* Add option for Append Processor to skip/allow empty values If one is using templates to generate values, this option can be helpful to avoid adding values that resolve into empty strings Fixes #104813 * Change allow_empty_values to ignore_empty_values * Update docs/changelog/105718.yaml * Handle nulls as well The original version of this PR predated `copy_from`, so the value wouldn't have been able to be null here. But now that `copy_from` exists we should handle null as well as empty strings. * Rewrite setFieldValue in terms of valueNotEmpty Since it handles nulls now, this logic is identical. * Rewrite another setFieldValue arity, too This one is a bit trickier, so I've lampshaded the surprising part with a comment, and also there's a newly added test on main via * Verify an invariant This arity of setFieldValue doesn't handle the single-value ignore_empty_value case (like in a set processor), it only handles the multi-value ignore_empty_values case (like in an append processor). The same thing applies to allow_duplicates, that is also an append-only concern. * This test can't handle nulls anymore * Fix a typo * Declare these once and don't use the return value from processor.execute * Add some empty values into this test * Ignore empty values with getFieldValue and copy_from * Re-add the ignore_empty_values docs * It seems conventional to just label these '9.2' * Add an example * Better quoting * Add a test-only feature * Add some rest tests * Fix typos --------- Co-authored-by: Joe Gallo <[email protected]>
1 parent 23e8349 commit 72da17c

File tree

8 files changed

+431
-69
lines changed

8 files changed

+431
-69
lines changed

docs/changelog/105718.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 105718
2+
summary: Add option for Append Processor to skip/allow empty values
3+
area: Ingest Node
4+
type: enhancement
5+
issues:
6+
- 104813

docs/reference/enrich-processor/append-processor.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,22 @@ $$$append-options$$$
1515
| --- | --- | --- | --- |
1616
| `field` | yes | - | The field to be appended to. Supports [template snippets](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#template-snippets). |
1717
| `value` | yes* | - | The value to be appended. Supports [template snippets](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#template-snippets). May specify only one of `value` or `copy_from`. |
18-
| `copy_from` {applies_to}`stack: ga 9.2.0` | no | - | The origin field which will be appended to `field`, cannot set `value` simultaneously. |
18+
| `copy_from` {applies_to}`stack: ga 9.2` | no | - | The origin field which will be appended to `field`, cannot set `value` simultaneously. |
1919
| `allow_duplicates` | no | true | If `false`, the processor does not appendvalues already present in the field. |
20+
| `ignore_empty_values` {applies_to}`stack: ga 9.2` | no | false | If `true`, the processor does not append values that resolve to `null` or an empty string.
2021
| `media_type` | no | `application/json` | The media type for encoding `value`. Applies only when `value` is a [template snippet](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#template-snippets). Must be one of `application/json`, `text/plain`, or`application/x-www-form-urlencoded`. |
2122
| `description` | no | - | Description of the processor. Useful for describing the purpose of the processor or its configuration. |
2223
| `if` | no | - | Conditionally execute the processor. See [Conditionally run a processor](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#conditionally-run-processor). |
2324
| `ignore_failure` | no | `false` | Ignore failures for the processor. See [Handling pipeline failures](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#handling-pipeline-failures). |
2425
| `on_failure` | no | - | Handle failures for the processor. See [Handling pipeline failures](docs-content://manage-data/ingest/transform-enrich/ingest-pipelines.md#handling-pipeline-failures). |
2526
| `tag` | no | - | Identifier for the processor. Useful for debugging and metrics. |
2627

28+
## Examples [append-processor-examples]
29+
30+
### Simple example [append-processor-simple-example]
31+
32+
Here is an `append` processor definition that adds the string `"production"` as well as the values of the `app` and `owner` fields to the `tags` field:
33+
2734
```js
2835
{
2936
"append": {
@@ -33,3 +40,21 @@ $$$append-options$$$
3340
}
3441
```
3542

43+
### Example using `allow_duplicates` and `ignore_empty_values` [append-processor-example-using-allow-duplicates-and-ignore-empty-values]
44+
45+
```{applies_to}
46+
stack: ga 9.2
47+
```
48+
49+
By using `allow_duplicates` and `ignore_empty_values`, it is possible to only append the `host.name` to the `related.hosts` if the `host.name` is not empty and if the value is not already present in `related.hosts`:
50+
51+
```js
52+
{
53+
"append": {
54+
"field": "related.hosts",
55+
"copy_from": "host.name",
56+
"allow_duplicates": false,
57+
"ignore_empty_values": true
58+
}
59+
}
60+
```

modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/AppendProcessor.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,23 @@ public final class AppendProcessor extends AbstractProcessor {
3636
private final ValueSource value;
3737
private final String copyFrom;
3838
private final boolean allowDuplicates;
39+
private final boolean ignoreEmptyValues;
3940

4041
AppendProcessor(
4142
String tag,
4243
String description,
4344
TemplateScript.Factory field,
4445
ValueSource value,
4546
String copyFrom,
46-
boolean allowDuplicates
47+
boolean allowDuplicates,
48+
boolean ignoreEmptyValues
4749
) {
4850
super(tag, description);
4951
this.field = field;
5052
this.value = value;
5153
this.copyFrom = copyFrom;
5254
this.allowDuplicates = allowDuplicates;
55+
this.ignoreEmptyValues = ignoreEmptyValues;
5356
}
5457

5558
public TemplateScript.Factory getField() {
@@ -68,10 +71,10 @@ public String getCopyFrom() {
6871
public IngestDocument execute(IngestDocument document) throws Exception {
6972
String path = document.renderTemplate(field);
7073
if (copyFrom != null) {
71-
Object fieldValue = document.getFieldValue(copyFrom, Object.class);
72-
document.appendFieldValue(path, IngestDocument.deepCopy(fieldValue), allowDuplicates);
74+
Object fieldValue = document.getFieldValue(copyFrom, Object.class, ignoreEmptyValues);
75+
document.appendFieldValue(path, IngestDocument.deepCopy(fieldValue), allowDuplicates, ignoreEmptyValues);
7376
} else {
74-
document.appendFieldValue(path, value, allowDuplicates);
77+
document.appendFieldValue(path, value, allowDuplicates, ignoreEmptyValues);
7578
}
7679
return document;
7780
}
@@ -116,9 +119,17 @@ public AppendProcessor create(
116119
}
117120
}
118121
boolean allowDuplicates = ConfigurationUtils.readBooleanProperty(TYPE, processorTag, config, "allow_duplicates", true);
122+
boolean ignoreEmptyValues = ConfigurationUtils.readBooleanProperty(TYPE, processorTag, config, "ignore_empty_values", false);
119123
TemplateScript.Factory compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag, "field", field, scriptService);
120-
121-
return new AppendProcessor(processorTag, description, compiledTemplate, valueSource, copyFrom, allowDuplicates);
124+
return new AppendProcessor(
125+
processorTag,
126+
description,
127+
compiledTemplate,
128+
valueSource,
129+
copyFrom,
130+
allowDuplicates,
131+
ignoreEmptyValues
132+
);
122133
}
123134
}
124135
}

0 commit comments

Comments
 (0)