Re-enable support for array-valued geo_shape fields. (#58786) (#58943)

A regression in the mapping code led to geo_shape no longer supporting
array-valued fields. This commit fixes this support and adds an integration
test to make sure this problem does not return!
This commit is contained in:
Tal Levy 2020-07-02 11:21:55 -07:00 committed by GitHub
parent d825d4352c
commit d516959774
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 180 additions and 5 deletions

View File

@ -286,11 +286,6 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
protected abstract void addDocValuesFields(String name, Processed geometry, List<IndexableField> fields, ParseContext context);
protected abstract void addMultiFields(ParseContext context, Processed geometry) throws IOException;
@Override
public final boolean parsesArrayValue() {
return true;
}
/** parsing logic for geometry indexing */
@Override
public void parse(ParseContext context) throws IOException {

View File

@ -130,6 +130,11 @@ public abstract class AbstractPointGeometryFieldMapper<Parsed, Processed> extend
this.nullValue = nullValue;
}
@Override
public final boolean parsesArrayValue() {
return true;
}
@Override
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
AbstractPointGeometryFieldMapper gpfm = (AbstractPointGeometryFieldMapper)other;

View File

@ -198,6 +198,11 @@ public abstract class AbstractShapeGeometryFieldMapper<Parsed, Processed> extend
this.orientation = orientation;
}
@Override
public final boolean parsesArrayValue() {
return false;
}
@Override
protected final void mergeOptions(FieldMapper other, List<String> conflicts) {
AbstractShapeGeometryFieldMapper gsfm = (AbstractShapeGeometryFieldMapper)other;

View File

@ -18,13 +18,16 @@
*/
package org.elasticsearch.index.mapper;
import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.InternalSettingsPlugin;
import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin;
@ -38,6 +41,7 @@ import java.util.Set;
import static org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.Names.IGNORE_Z_VALUE;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
public class GeoShapeFieldMapperTests extends FieldMapperTestCase<GeoShapeFieldMapper.Builder> {
@ -302,6 +306,43 @@ public class GeoShapeFieldMapperTests extends FieldMapperTestCase<GeoShapeFieldM
}
}
public void testGeoShapeArrayParsing() throws Exception {
String mapping = Strings.toString(XContentFactory.jsonBuilder()
.startObject()
.startObject("_doc")
.startObject("properties")
.startObject("location")
.field("type", "geo_shape")
.endObject()
.endObject()
.endObject()
.endObject());
DocumentMapper mapper = createIndex("test").mapperService().documentMapperParser()
.parse("_doc", new CompressedXContent(mapping));
BytesReference arrayedDoc = BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject()
.startArray("shape")
.startObject()
.field("type", "Point")
.startArray("coordinates").value(176.0).value(15.0).endArray()
.endObject()
.startObject()
.field("type", "Point")
.startArray("coordinates").value(76.0).value(-15.0).endArray()
.endObject()
.endArray()
.endObject()
);
SourceToParse sourceToParse = new SourceToParse("test", "_doc", "1", arrayedDoc, XContentType.JSON);
ParsedDocument document = mapper.parse(sourceToParse);
assertThat(document.docs(), hasSize(1));
IndexableField[] fields = document.docs().get(0).getFields("shape.type");
assertThat(fields.length, equalTo(2));
}
public String toXContentString(GeoShapeFieldMapper mapper, boolean includeDefaults) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
ToXContent.Params params;

View File

@ -18,6 +18,7 @@
*/
package org.elasticsearch.index.mapper;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.spatial.prefix.PrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
@ -26,6 +27,7 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.geo.ShapeRelation;
@ -34,6 +36,7 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.geometry.Point;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.plugins.Plugin;
@ -49,6 +52,7 @@ import java.util.Set;
import static org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.Names.IGNORE_Z_VALUE;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.mock;
@ -783,6 +787,45 @@ public class LegacyGeoShapeFieldMapperTests extends FieldMapperTestCase<LegacyGe
);
}
public void testGeoShapeArrayParsing() throws Exception {
String mapping = Strings.toString(XContentFactory.jsonBuilder()
.startObject()
.startObject("_doc")
.startObject("properties")
.startObject("location")
.field("type", "geo_shape")
.field("tree", "quadtree")
.endObject()
.endObject()
.endObject()
.endObject());
DocumentMapper mapper = createIndex("test").mapperService().documentMapperParser()
.parse("_doc", new CompressedXContent(mapping));
BytesReference arrayedDoc = BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject()
.startArray("shape")
.startObject()
.field("type", "Point")
.startArray("coordinates").value(176.0).value(15.0).endArray()
.endObject()
.startObject()
.field("type", "Point")
.startArray("coordinates").value(76.0).value(-15.0).endArray()
.endObject()
.endArray()
.endObject()
);
SourceToParse sourceToParse = new SourceToParse("test", "_doc", "1", arrayedDoc, XContentType.JSON);
ParsedDocument document = mapper.parse(sourceToParse);
assertThat(document.docs(), hasSize(1));
IndexableField[] fields = document.docs().get(0).getFields("shape.type");
assertThat(fields.length, equalTo(2));
assertFieldWarnings("tree");
}
public String toXContentString(LegacyGeoShapeFieldMapper mapper, boolean includeDefaults) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
ToXContent.Params params;

View File

@ -24,20 +24,25 @@
*/
package org.elasticsearch.xpack.spatial.index.mapper;
import org.apache.lucene.index.IndexableField;
import org.elasticsearch.Version;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.FieldMapperTestCase;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.SourceToParse;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.InternalSettingsPlugin;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
@ -52,6 +57,7 @@ import java.util.Set;
import static org.elasticsearch.index.mapper.AbstractPointGeometryFieldMapper.Names.IGNORE_Z_VALUE;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
public class GeoShapeWithDocValuesFieldMapperTests extends FieldMapperTestCase<GeoShapeWithDocValuesFieldMapper.Builder> {
@ -394,6 +400,43 @@ public class GeoShapeWithDocValuesFieldMapperTests extends FieldMapperTestCase<G
assertTrue(serialized, serialized.contains("\"doc_values\":" + docValues));
}
public void testGeoShapeArrayParsing() throws Exception {
String mapping = Strings.toString(XContentFactory.jsonBuilder()
.startObject()
.startObject("_doc")
.startObject("properties")
.startObject("location")
.field("type", "geo_shape")
.endObject()
.endObject()
.endObject()
.endObject());
DocumentMapper mapper = createIndex("test").mapperService().documentMapperParser()
.parse("_doc", new CompressedXContent(mapping));
BytesReference arrayedDoc = BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject()
.startArray("shape")
.startObject()
.field("type", "Point")
.startArray("coordinates").value(176.0).value(15.0).endArray()
.endObject()
.startObject()
.field("type", "Point")
.startArray("coordinates").value(76.0).value(-15.0).endArray()
.endObject()
.endArray()
.endObject()
);
SourceToParse sourceToParse = new SourceToParse("test", "_doc", "1", arrayedDoc, XContentType.JSON);
ParsedDocument document = mapper.parse(sourceToParse);
assertThat(document.docs(), hasSize(1));
IndexableField[] fields = document.docs().get(0).getFields("shape.type");
assertThat(fields.length, equalTo(2));
}
public String toXContentString(GeoShapeWithDocValuesFieldMapper mapper, boolean includeDefaults) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
ToXContent.Params params;

View File

@ -5,24 +5,30 @@
*/
package org.elasticsearch.xpack.spatial.index.mapper;
import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.SourceToParse;
import java.io.IOException;
import java.util.Collections;
import static org.elasticsearch.index.mapper.AbstractPointGeometryFieldMapper.Names.IGNORE_Z_VALUE;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
/** testing for {@link org.elasticsearch.xpack.spatial.index.mapper.ShapeFieldMapper} */
@ -268,6 +274,43 @@ public class ShapeFieldMapperTests extends CartesianFieldMapperTests {
}
}
public void testShapeArrayParsing() throws Exception {
String mapping = Strings.toString(XContentFactory.jsonBuilder()
.startObject()
.startObject("_doc")
.startObject("properties")
.startObject("location")
.field("type", "shape")
.endObject()
.endObject()
.endObject()
.endObject());
DocumentMapper mapper = createIndex("test").mapperService().documentMapperParser()
.parse("_doc", new CompressedXContent(mapping));
BytesReference arrayedDoc = BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject()
.startArray("shape")
.startObject()
.field("type", "Point")
.startArray("coordinates").value(176.0).value(15.0).endArray()
.endObject()
.startObject()
.field("type", "Point")
.startArray("coordinates").value(76.0).value(-15.0).endArray()
.endObject()
.endArray()
.endObject()
);
SourceToParse sourceToParse = new SourceToParse("test", "_doc", "1", arrayedDoc, XContentType.JSON);
ParsedDocument document = mapper.parse(sourceToParse);
assertThat(document.docs(), hasSize(1));
IndexableField[] fields = document.docs().get(0).getFields("shape.type");
assertThat(fields.length, equalTo(2));
}
public String toXContentString(ShapeFieldMapper mapper, boolean includeDefaults) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
ToXContent.Params params;