Browse Source

[ML] Anomaly detection jobs should allow missing values for geo fields (#57300)

Allows geo fields (`geo_point`, `geo_shape`) to have missing values.
Fixes a bug where such missing values would result in an error.

Closes #57299
Dimitris Athanasiou 5 years ago
parent
commit
d26f63d062

+ 5 - 1
x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/extractor/GeoPointField.java

@@ -24,9 +24,13 @@ public class GeoPointField extends DocValueField {
     @Override
     public Object[] value(SearchHit hit) {
         Object[] value = super.value(hit);
-        if (value.length != 1) {
+        if (value.length == 0) {
+            return value;
+        }
+        if (value.length > 1) {
             throw new IllegalStateException("Unexpected values for a geo_point field: " + Arrays.toString(value));
         }
+
         if (value[0] instanceof String) {
             value[0] = handleString((String) value[0]);
         } else {

+ 5 - 1
x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/extractor/GeoShapeField.java

@@ -36,9 +36,13 @@ public class GeoShapeField extends SourceField {
     @Override
     public Object[] value(SearchHit hit) {
         Object[] value = super.value(hit);
-        if (value.length != 1) {
+        if (value.length == 0) {
+            return value;
+        }
+        if (value.length > 1) {
             throw new IllegalStateException("Unexpected values for a geo_shape field: " + Arrays.toString(value));
         }
+
         if (value[0] instanceof String) {
             value[0] = handleString((String) value[0]);
         } else if (value[0] instanceof Map<?, ?>) {

+ 19 - 0
x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/extractor/GeoPointFieldTests.java

@@ -9,6 +9,8 @@ import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.test.ESTestCase;
 import org.elasticsearch.xpack.ml.test.SearchHitBuilder;
 
+import java.util.Arrays;
+
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
@@ -36,4 +38,21 @@ public class GeoPointFieldTests extends ESTestCase {
         assertThat(geo.isMultiField(), is(false));
         expectThrows(UnsupportedOperationException.class, () -> geo.getParentField());
     }
+
+    public void testMissing() {
+        SearchHit hit = new SearchHitBuilder(42).addField("a_keyword", "bar").build();
+
+        ExtractedField geo = new GeoPointField("missing");
+
+        assertThat(geo.value(hit), equalTo(new Object[0]));
+    }
+
+    public void testArray() {
+        SearchHit hit = new SearchHitBuilder(42).addField("geo", Arrays.asList(1, 2)).build();
+
+        ExtractedField geo = new GeoPointField("geo");
+
+        IllegalStateException e = expectThrows(IllegalStateException.class, () -> geo.value(hit));
+        assertThat(e.getMessage(), equalTo("Unexpected values for a geo_point field: [1, 2]"));
+    }
 }

+ 17 - 0
x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/extractor/GeoShapeFieldTests.java

@@ -59,4 +59,21 @@ public class GeoShapeFieldTests extends ESTestCase {
         assertThat(geo.isMultiField(), is(false));
         expectThrows(UnsupportedOperationException.class, () -> geo.getParentField());
     }
+
+    public void testMissing() {
+        SearchHit hit = new SearchHitBuilder(42).addField("a_keyword", "bar").build();
+
+        ExtractedField geo = new GeoShapeField("missing");
+
+        assertThat(geo.value(hit), equalTo(new Object[0]));
+    }
+
+    public void testArray() {
+        SearchHit hit = new SearchHitBuilder(42).setSource("{\"geo\":[1,2]}").build();
+
+        ExtractedField geo = new GeoShapeField("geo");
+
+        IllegalStateException e = expectThrows(IllegalStateException.class, () -> geo.value(hit));
+        assertThat(e.getMessage(), equalTo("Unexpected values for a geo_shape field: [1, 2]"));
+    }
 }