add `ignore_missing` option to SplitProcessor (#20982)

Closes #20840.
This commit is contained in:
Tal Levy 2016-11-16 15:46:09 +02:00 committed by GitHub
parent 04b712bdc5
commit 6796464f16
8 changed files with 73 additions and 43 deletions

View File

@ -116,6 +116,28 @@ public final class IngestDocument {
return cast(path, context, clazz); return cast(path, context, clazz);
} }
/**
* Returns the value contained in the document for the provided path
*
* @param path The path within the document in dot-notation
* @param clazz The expected class of the field value
* @param ignoreMissing The flag to determine whether to throw an exception when `path` is not found in the document.
* @return the value for the provided path if existing, null otherwise.
* @throws IllegalArgumentException only if ignoreMissing is false and the path is null, empty, invalid, if the field doesn't exist
* or if the field that is found at the provided path is not of the expected type.
*/
public <T> T getFieldValue(String path, Class<T> clazz, boolean ignoreMissing) {
try {
return getFieldValue(path, clazz);
} catch (IllegalArgumentException e) {
if (ignoreMissing && hasField(path) != true) {
return null;
} else {
throw e;
}
}
}
/** /**
* Returns the value contained in the document with the provided templated path * Returns the value contained in the document with the provided templated path
* @param pathTemplate The path within the document in dot-notation * @param pathTemplate The path within the document in dot-notation

View File

@ -1630,6 +1630,7 @@ Splits a field into an array using a separator character. Only works on string f
| Name | Required | Default | Description | Name | Required | Default | Description
| `field` | yes | - | The field to split | `field` | yes | - | The field to split
| `separator` | yes | - | A regex which matches the separator, eg `,` or `\s+` | `separator` | yes | - | A regex which matches the separator, eg `,` or `\s+`
| `ignore_missing` | no | `false` | If `true` and `field` does not exist, the processor quietly exits without modifying the document
|====== |======
[source,js] [source,js]

View File

@ -34,7 +34,7 @@ abstract class AbstractStringProcessor extends AbstractProcessor {
private final String field; private final String field;
private final boolean ignoreMissing; private final boolean ignoreMissing;
protected AbstractStringProcessor(String tag, String field, boolean ignoreMissing) { AbstractStringProcessor(String tag, String field, boolean ignoreMissing) {
super(tag); super(tag);
this.field = field; this.field = field;
this.ignoreMissing = ignoreMissing; this.ignoreMissing = ignoreMissing;
@ -50,16 +50,8 @@ abstract class AbstractStringProcessor extends AbstractProcessor {
@Override @Override
public final void execute(IngestDocument document) { public final void execute(IngestDocument document) {
String val; String val = document.getFieldValue(field, String.class, ignoreMissing);
try {
val = document.getFieldValue(field, String.class);
} catch (IllegalArgumentException e) {
if (ignoreMissing && document.hasField(field) != true) {
return;
}
throw e;
}
if (val == null && ignoreMissing) { if (val == null && ignoreMissing) {
return; return;
} else if (val == null) { } else if (val == null) {
@ -72,7 +64,7 @@ abstract class AbstractStringProcessor extends AbstractProcessor {
protected abstract String process(String value); protected abstract String process(String value);
abstract static class Factory implements Processor.Factory { abstract static class Factory implements Processor.Factory {
protected final String processorType; final String processorType;
protected Factory(String processorType) { protected Factory(String processorType) {
this.processorType = processorType; this.processorType = processorType;

View File

@ -142,18 +142,9 @@ public final class ConvertProcessor extends AbstractProcessor {
@Override @Override
public void execute(IngestDocument document) { public void execute(IngestDocument document) {
Object oldValue = null; Object oldValue = document.getFieldValue(field, Object.class, ignoreMissing);
Object newValue; Object newValue;
try {
oldValue = document.getFieldValue(field, Object.class);
} catch (IllegalArgumentException e) {
if (ignoreMissing) {
return;
}
throw e;
}
if (oldValue == null && ignoreMissing) { if (oldValue == null && ignoreMissing) {
return; return;
} else if (oldValue == null) { } else if (oldValue == null) {

View File

@ -54,16 +54,7 @@ public final class GrokProcessor extends AbstractProcessor {
@Override @Override
public void execute(IngestDocument ingestDocument) throws Exception { public void execute(IngestDocument ingestDocument) throws Exception {
String fieldValue; String fieldValue = ingestDocument.getFieldValue(matchField, String.class, ignoreMissing);
try {
fieldValue = ingestDocument.getFieldValue(matchField, String.class);
} catch (IllegalArgumentException e) {
if (ignoreMissing && ingestDocument.hasField(matchField) != true) {
return;
}
throw e;
}
if (fieldValue == null && ignoreMissing) { if (fieldValue == null && ignoreMissing) {
return; return;

View File

@ -40,11 +40,13 @@ public final class SplitProcessor extends AbstractProcessor {
private final String field; private final String field;
private final String separator; private final String separator;
private final boolean ignoreMissing;
SplitProcessor(String tag, String field, String separator) { SplitProcessor(String tag, String field, String separator, boolean ignoreMissing) {
super(tag); super(tag);
this.field = field; this.field = field;
this.separator = separator; this.separator = separator;
this.ignoreMissing = ignoreMissing;
} }
String getField() { String getField() {
@ -55,12 +57,20 @@ public final class SplitProcessor extends AbstractProcessor {
return separator; return separator;
} }
boolean isIgnoreMissing() {
return ignoreMissing;
}
@Override @Override
public void execute(IngestDocument document) { public void execute(IngestDocument document) {
String oldVal = document.getFieldValue(field, String.class); String oldVal = document.getFieldValue(field, String.class, ignoreMissing);
if (oldVal == null) {
if (oldVal == null && ignoreMissing) {
return;
} else if (oldVal == null) {
throw new IllegalArgumentException("field [" + field + "] is null, cannot split."); throw new IllegalArgumentException("field [" + field + "] is null, cannot split.");
} }
String[] strings = oldVal.split(separator); String[] strings = oldVal.split(separator);
List<String> splitList = new ArrayList<>(strings.length); List<String> splitList = new ArrayList<>(strings.length);
Collections.addAll(splitList, strings); Collections.addAll(splitList, strings);
@ -77,7 +87,9 @@ public final class SplitProcessor extends AbstractProcessor {
public SplitProcessor create(Map<String, Processor.Factory> registry, String processorTag, public SplitProcessor create(Map<String, Processor.Factory> registry, String processorTag,
Map<String, Object> config) throws Exception { Map<String, Object> config) throws Exception {
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field"); String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field");
return new SplitProcessor(processorTag, field, ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "separator")); boolean ignoreMissing = ConfigurationUtils.readBooleanProperty(TYPE, processorTag, config, "ignore_missing", false);
return new SplitProcessor(processorTag, field,
ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "separator"), ignoreMissing);
} }
} }
} }

View File

@ -39,6 +39,7 @@ public class SplitProcessorFactoryTests extends ESTestCase {
assertThat(splitProcessor.getTag(), equalTo(processorTag)); assertThat(splitProcessor.getTag(), equalTo(processorTag));
assertThat(splitProcessor.getField(), equalTo("field1")); assertThat(splitProcessor.getField(), equalTo("field1"));
assertThat(splitProcessor.getSeparator(), equalTo("\\.")); assertThat(splitProcessor.getSeparator(), equalTo("\\."));
assertFalse(splitProcessor.isIgnoreMissing());
} }
public void testCreateNoFieldPresent() throws Exception { public void testCreateNoFieldPresent() throws Exception {

View File

@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.ingest.IngestDocumentMatcher.assertIngestDocument;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -38,7 +39,7 @@ public class SplitProcessorTests extends ESTestCase {
public void testSplit() throws Exception { public void testSplit() throws Exception {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random()); IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random());
String fieldName = RandomDocumentPicks.addRandomField(random(), ingestDocument, "127.0.0.1"); String fieldName = RandomDocumentPicks.addRandomField(random(), ingestDocument, "127.0.0.1");
Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\."); Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\.", false);
processor.execute(ingestDocument); processor.execute(ingestDocument);
assertThat(ingestDocument.getFieldValue(fieldName, List.class), equalTo(Arrays.asList("127", "0", "0", "1"))); assertThat(ingestDocument.getFieldValue(fieldName, List.class), equalTo(Arrays.asList("127", "0", "0", "1")));
} }
@ -46,7 +47,7 @@ public class SplitProcessorTests extends ESTestCase {
public void testSplitFieldNotFound() throws Exception { public void testSplitFieldNotFound() throws Exception {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>()); IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>());
String fieldName = RandomDocumentPicks.randomFieldName(random()); String fieldName = RandomDocumentPicks.randomFieldName(random());
Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\."); Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\.", false);
try { try {
processor.execute(ingestDocument); processor.execute(ingestDocument);
fail("split processor should have failed"); fail("split processor should have failed");
@ -56,8 +57,9 @@ public class SplitProcessorTests extends ESTestCase {
} }
public void testSplitNullValue() throws Exception { public void testSplitNullValue() throws Exception {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), Collections.singletonMap("field", null)); IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(),
Processor processor = new SplitProcessor(randomAsciiOfLength(10), "field", "\\."); Collections.singletonMap("field", null));
Processor processor = new SplitProcessor(randomAsciiOfLength(10), "field", "\\.", false);
try { try {
processor.execute(ingestDocument); processor.execute(ingestDocument);
fail("split processor should have failed"); fail("split processor should have failed");
@ -66,11 +68,29 @@ public class SplitProcessorTests extends ESTestCase {
} }
} }
public void testSplitNullValueWithIgnoreMissing() throws Exception {
String fieldName = RandomDocumentPicks.randomFieldName(random());
IngestDocument originalIngestDocument = RandomDocumentPicks.randomIngestDocument(random(),
Collections.singletonMap(fieldName, null));
IngestDocument ingestDocument = new IngestDocument(originalIngestDocument);
Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\.", true);
processor.execute(ingestDocument);
assertIngestDocument(originalIngestDocument, ingestDocument);
}
public void testSplitNonExistentWithIgnoreMissing() throws Exception {
IngestDocument originalIngestDocument = RandomDocumentPicks.randomIngestDocument(random(), Collections.emptyMap());
IngestDocument ingestDocument = new IngestDocument(originalIngestDocument);
Processor processor = new SplitProcessor(randomAsciiOfLength(10), "field", "\\.", true);
processor.execute(ingestDocument);
assertIngestDocument(originalIngestDocument, ingestDocument);
}
public void testSplitNonStringValue() throws Exception { public void testSplitNonStringValue() throws Exception {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>()); IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>());
String fieldName = RandomDocumentPicks.randomFieldName(random()); String fieldName = RandomDocumentPicks.randomFieldName(random());
ingestDocument.setFieldValue(fieldName, randomInt()); ingestDocument.setFieldValue(fieldName, randomInt());
Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\."); Processor processor = new SplitProcessor(randomAsciiOfLength(10), fieldName, "\\.", false);
try { try {
processor.execute(ingestDocument); processor.execute(ingestDocument);
fail("split processor should have failed"); fail("split processor should have failed");