Skip to content

Commit 43d6720

Browse files
committed
Add target_field parameter to gsub, join, lowercase, sort, split, trim
and uppercase processors
1 parent 7ab3d5d commit 43d6720

26 files changed

+475
-292
lines changed

docs/reference/ingest/ingest-node.asciidoc

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,10 +1489,12 @@ If the field is not a string, the processor will throw an exception.
14891489
.Gsub Options
14901490
[options="header"]
14911491
|======
1492-
| Name | Required | Default | Description
1493-
| `field` | yes | - | The field to apply the replacement to
1494-
| `pattern` | yes | - | The pattern to be replaced
1495-
| `replacement` | yes | - | The string to replace the matching patterns with
1492+
| Name | Required | Default | Description
1493+
| `field` | yes | - | The field to apply the replacement to
1494+
| `pattern` | yes | - | The pattern to be replaced
1495+
| `replacement` | yes | - | The string to replace the matching patterns with
1496+
| `target_field` | no | `field` | The field to assign the converted value to, by default `field` is updated in-place
1497+
| `ignore_missing` | no | `false` | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document
14961498
|======
14971499

14981500
[source,js]
@@ -1516,9 +1518,10 @@ Throws an error when the field is not an array.
15161518
.Join Options
15171519
[options="header"]
15181520
|======
1519-
| Name | Required | Default | Description
1520-
| `field` | yes | - | The field to be separated
1521-
| `separator` | yes | - | The separator character
1521+
| Name | Required | Default | Description
1522+
| `field` | yes | - | The field to be separated
1523+
| `separator` | yes | - | The separator character
1524+
| `target_field` | no | `field` | The field to assign the joined value to, by default `field` is updated in-place
15221525
|======
15231526

15241527
[source,js]
@@ -1662,6 +1665,7 @@ Converts a string to its lowercase equivalent.
16621665
|======
16631666
| Name | Required | Default | Description
16641667
| `field` | yes | - | The field to make lowercase
1668+
| `target_field` | no | `field` | The field to assign the converted value to, by default `field` is updated in-place
16651669
| `ignore_missing` | no | `false` | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document
16661670
|======
16671671

@@ -1874,6 +1878,7 @@ Splits a field into an array using a separator character. Only works on string f
18741878
| Name | Required | Default | Description
18751879
| `field` | yes | - | The field to split
18761880
| `separator` | yes | - | A regex which matches the separator, eg `,` or `\s+`
1881+
| `target_field` | no | `field` | The field to assign the split value to, by default `field` is updated in-place
18771882
| `ignore_missing` | no | `false` | If `true` and `field` does not exist, the processor quietly exits without modifying the document
18781883
|======
18791884

@@ -1899,9 +1904,10 @@ Throws an error when the field is not an array.
18991904
.Sort Options
19001905
[options="header"]
19011906
|======
1902-
| Name | Required | Default | Description
1903-
| `field` | yes | - | The field to be sorted
1904-
| `order` | no | `"asc"` | The sort order to use. Accepts `"asc"` or `"desc"`.
1907+
| Name | Required | Default | Description
1908+
| `field` | yes | - | The field to be sorted
1909+
| `order` | no | `"asc"` | The sort order to use. Accepts `"asc"` or `"desc"`.
1910+
| `target_field` | no | `field` | The field to assign the sorted value to, by default `field` is updated in-place
19051911
|======
19061912

19071913
[source,js]
@@ -1927,6 +1933,7 @@ NOTE: This only works on leading and trailing whitespace.
19271933
|======
19281934
| Name | Required | Default | Description
19291935
| `field` | yes | - | The string-valued field to trim whitespace from
1936+
| `target_field` | no | `field` | The field to assign the trimmed value to, by default `field` is updated in-place
19301937
| `ignore_missing` | no | `false` | If `true` and `field` does not exist, the processor quietly exits without modifying the document
19311938
|======
19321939

@@ -1950,6 +1957,7 @@ Converts a string to its uppercase equivalent.
19501957
|======
19511958
| Name | Required | Default | Description
19521959
| `field` | yes | - | The field to make uppercase
1960+
| `target_field` | no | `field` | The field to assign the converted value to, by default `field` is updated in-place
19531961
| `ignore_missing` | no | `false` | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document
19541962
|======
19551963

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
abstract class AbstractStringProcessor extends AbstractProcessor {
3434
private final String field;
3535
private final boolean ignoreMissing;
36+
private final String targetField;
3637

37-
AbstractStringProcessor(String tag, String field, boolean ignoreMissing) {
38+
AbstractStringProcessor(String tag, String field, boolean ignoreMissing, String targetField) {
3839
super(tag);
3940
this.field = field;
4041
this.ignoreMissing = ignoreMissing;
42+
this.targetField = targetField;
4143
}
4244

4345
public String getField() {
@@ -48,6 +50,10 @@ boolean isIgnoreMissing() {
4850
return ignoreMissing;
4951
}
5052

53+
String getTargetField() {
54+
return targetField;
55+
}
56+
5157
@Override
5258
public final void execute(IngestDocument document) {
5359
String val = document.getFieldValue(field, String.class, ignoreMissing);
@@ -58,7 +64,7 @@ public final void execute(IngestDocument document) {
5864
throw new IllegalArgumentException("field [" + field + "] is null, cannot process it.");
5965
}
6066

61-
document.setFieldValue(field, process(val));
67+
document.setFieldValue(targetField, process(val));
6268
}
6369

6470
protected abstract String process(String value);
@@ -75,9 +81,12 @@ public AbstractStringProcessor create(Map<String, Processor.Factory> registry, S
7581
Map<String, Object> config) throws Exception {
7682
String field = ConfigurationUtils.readStringProperty(processorType, tag, config, "field");
7783
boolean ignoreMissing = ConfigurationUtils.readBooleanProperty(processorType, tag, config, "ignore_missing", false);
78-
return newProcessor(tag, field, ignoreMissing);
84+
String targetField = ConfigurationUtils.readStringProperty(processorType, tag, config, "target_field", field);
85+
86+
return newProcessor(tag, config, field, ignoreMissing, targetField);
7987
}
8088

81-
protected abstract AbstractStringProcessor newProcessor(String processorTag, String field, boolean ignoreMissing);
89+
protected abstract AbstractStringProcessor newProcessor(String processorTag, Map<String, Object> config, String field,
90+
boolean ignoreMissing, String targetField);
8291
}
8392
}

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

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@
1919

2020
package org.elasticsearch.ingest.common;
2121

22-
import org.elasticsearch.ingest.AbstractProcessor;
23-
import org.elasticsearch.ingest.IngestDocument;
24-
import org.elasticsearch.ingest.Processor;
25-
2622
import java.util.Map;
27-
import java.util.regex.Matcher;
2823
import java.util.regex.Pattern;
2924

3025
import static org.elasticsearch.ingest.ConfigurationUtils.newConfigurationException;
@@ -34,25 +29,19 @@
3429
* Processor that allows to search for patterns in field content and replace them with corresponding string replacement.
3530
* Support fields of string type only, throws exception if a field is of a different type.
3631
*/
37-
public final class GsubProcessor extends AbstractProcessor {
32+
public final class GsubProcessor extends AbstractStringProcessor {
3833

3934
public static final String TYPE = "gsub";
4035

41-
private final String field;
4236
private final Pattern pattern;
4337
private final String replacement;
4438

45-
GsubProcessor(String tag, String field, Pattern pattern, String replacement) {
46-
super(tag);
47-
this.field = field;
39+
GsubProcessor(String tag, String field, Pattern pattern, String replacement, boolean ignoreMissing, String targetField) {
40+
super(tag, field, ignoreMissing, targetField);
4841
this.pattern = pattern;
4942
this.replacement = replacement;
5043
}
5144

52-
String getField() {
53-
return field;
54-
}
55-
5645
Pattern getPattern() {
5746
return pattern;
5847
}
@@ -61,28 +50,25 @@ String getReplacement() {
6150
return replacement;
6251
}
6352

64-
6553
@Override
66-
public void execute(IngestDocument document) {
67-
String oldVal = document.getFieldValue(field, String.class);
68-
if (oldVal == null) {
69-
throw new IllegalArgumentException("field [" + field + "] is null, cannot match pattern.");
70-
}
71-
Matcher matcher = pattern.matcher(oldVal);
72-
String newVal = matcher.replaceAll(replacement);
73-
document.setFieldValue(field, newVal);
54+
protected String process(String value) {
55+
return pattern.matcher(value).replaceAll(replacement);
7456
}
7557

7658
@Override
7759
public String getType() {
7860
return TYPE;
7961
}
8062

81-
public static final class Factory implements Processor.Factory {
63+
public static final class Factory extends AbstractStringProcessor.Factory {
64+
65+
public Factory() {
66+
super(TYPE);
67+
}
68+
8269
@Override
83-
public GsubProcessor create(Map<String, Processor.Factory> registry, String processorTag,
84-
Map<String, Object> config) throws Exception {
85-
String field = readStringProperty(TYPE, processorTag, config, "field");
70+
protected AbstractStringProcessor newProcessor(String processorTag, Map<String, Object> config, String field,
71+
boolean ignoreMissing, String targetField) {
8672
String pattern = readStringProperty(TYPE, processorTag, config, "pattern");
8773
String replacement = readStringProperty(TYPE, processorTag, config, "replacement");
8874
Pattern searchPattern;
@@ -91,7 +77,7 @@ public GsubProcessor create(Map<String, Processor.Factory> registry, String proc
9177
} catch (Exception e) {
9278
throw newConfigurationException(TYPE, processorTag, "pattern", "Invalid regex pattern. " + e.getMessage());
9379
}
94-
return new GsubProcessor(processorTag, field, searchPattern, replacement);
80+
return new GsubProcessor(processorTag, field, searchPattern, replacement, ignoreMissing, targetField);
9581
}
9682
}
9783
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ public final class JoinProcessor extends AbstractProcessor {
3838

3939
private final String field;
4040
private final String separator;
41+
private final String targetField;
4142

42-
JoinProcessor(String tag, String field, String separator) {
43+
JoinProcessor(String tag, String field, String separator, String targetField) {
4344
super(tag);
4445
this.field = field;
4546
this.separator = separator;
47+
this.targetField = targetField;
4648
}
4749

4850
String getField() {
@@ -53,6 +55,10 @@ String getSeparator() {
5355
return separator;
5456
}
5557

58+
String getTargetField() {
59+
return targetField;
60+
}
61+
5662
@Override
5763
public void execute(IngestDocument document) {
5864
List<?> list = document.getFieldValue(field, List.class);
@@ -62,7 +68,7 @@ public void execute(IngestDocument document) {
6268
String joined = list.stream()
6369
.map(Object::toString)
6470
.collect(Collectors.joining(separator));
65-
document.setFieldValue(field, joined);
71+
document.setFieldValue(targetField, joined);
6672
}
6773

6874
@Override
@@ -76,7 +82,8 @@ public JoinProcessor create(Map<String, Processor.Factory> registry, String proc
7682
Map<String, Object> config) throws Exception {
7783
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field");
7884
String separator = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "separator");
79-
return new JoinProcessor(processorTag, field, separator);
85+
String targetField = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "target_field", field);
86+
return new JoinProcessor(processorTag, field, separator, targetField);
8087
}
8188
}
8289
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.ingest.common;
2121

2222
import java.util.Locale;
23+
import java.util.Map;
2324

2425
/**
2526
* Processor that converts the content of string fields to lowercase.
@@ -30,8 +31,8 @@ public final class LowercaseProcessor extends AbstractStringProcessor {
3031

3132
public static final String TYPE = "lowercase";
3233

33-
LowercaseProcessor(String processorTag, String field, boolean ignoreMissing) {
34-
super(processorTag, field, ignoreMissing);
34+
LowercaseProcessor(String processorTag, String field, boolean ignoreMissing, String targetField) {
35+
super(processorTag, field, ignoreMissing, targetField);
3536
}
3637

3738
@Override
@@ -51,8 +52,9 @@ public Factory() {
5152
}
5253

5354
@Override
54-
protected LowercaseProcessor newProcessor(String tag, String field, boolean ignoreMissing) {
55-
return new LowercaseProcessor(tag, field, ignoreMissing);
55+
protected LowercaseProcessor newProcessor(String tag, Map<String, Object> config, String field,
56+
boolean ignoreMissing, String targetField) {
57+
return new LowercaseProcessor(tag, field, ignoreMissing, targetField);
5658
}
5759
}
5860
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ public static SortOrder fromString(String value) {
6969

7070
private final String field;
7171
private final SortOrder order;
72+
private final String targetField;
7273

73-
SortProcessor(String tag, String field, SortOrder order) {
74+
SortProcessor(String tag, String field, SortOrder order, String targetField) {
7475
super(tag);
7576
this.field = field;
7677
this.order = order;
78+
this.targetField = targetField;
7779
}
7880

7981
String getField() {
@@ -84,6 +86,10 @@ SortOrder getOrder() {
8486
return order;
8587
}
8688

89+
String getTargetField() {
90+
return targetField;
91+
}
92+
8793
@Override
8894
@SuppressWarnings("unchecked")
8995
public void execute(IngestDocument document) {
@@ -103,7 +109,7 @@ public void execute(IngestDocument document) {
103109
Collections.sort(list, Collections.reverseOrder());
104110
}
105111

106-
document.setFieldValue(field, list);
112+
document.setFieldValue(targetField, list);
107113
}
108114

109115
@Override
@@ -117,6 +123,7 @@ public static final class Factory implements Processor.Factory {
117123
public SortProcessor create(Map<String, Processor.Factory> registry, String processorTag,
118124
Map<String, Object> config) throws Exception {
119125
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, FIELD);
126+
String targetField = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "target_field", field);
120127
try {
121128
SortOrder direction = SortOrder.fromString(
122129
ConfigurationUtils.readStringProperty(
@@ -125,7 +132,7 @@ public SortProcessor create(Map<String, Processor.Factory> registry, String proc
125132
config,
126133
ORDER,
127134
DEFAULT_ORDER));
128-
return new SortProcessor(processorTag, field, direction);
135+
return new SortProcessor(processorTag, field, direction, targetField);
129136
} catch (IllegalArgumentException e) {
130137
throw ConfigurationUtils.newConfigurationException(TYPE, processorTag, ORDER, e.getMessage());
131138
}

0 commit comments

Comments
 (0)