Fix defaults in GeoShapeFieldMapper output (#31302)

GeoShapeFieldMapper should show actual defaults instead of placeholder
values when the mapping is requested with include_defaults=true.

Closes #23206
This commit is contained in:
Igor Motov 2018-06-18 13:50:52 -04:00 committed by GitHub
parent 340313b048
commit d9a6d69a0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 2 deletions

View File

@ -546,11 +546,24 @@ public class GeoShapeFieldMapper extends FieldMapper {
if (includeDefaults || fieldType().tree().equals(Defaults.TREE) == false) {
builder.field(Names.TREE, fieldType().tree());
}
if (includeDefaults || fieldType().treeLevels() != 0) {
if (fieldType().treeLevels() != 0) {
builder.field(Names.TREE_LEVELS, fieldType().treeLevels());
} else if(includeDefaults && fieldType().precisionInMeters() == -1) { // defaults only make sense if precision is not specified
if ("geohash".equals(fieldType().tree())) {
builder.field(Names.TREE_LEVELS, Defaults.GEOHASH_LEVELS);
} else if ("legacyquadtree".equals(fieldType().tree())) {
builder.field(Names.TREE_LEVELS, Defaults.QUADTREE_LEVELS);
} else if ("quadtree".equals(fieldType().tree())) {
builder.field(Names.TREE_LEVELS, Defaults.QUADTREE_LEVELS);
} else {
throw new IllegalArgumentException("Unknown prefix tree type [" + fieldType().tree() + "]");
}
}
if (includeDefaults || fieldType().precisionInMeters() != -1) {
if (fieldType().precisionInMeters() != -1) {
builder.field(Names.TREE_PRESISION, DistanceUnit.METERS.toString(fieldType().precisionInMeters()));
} else if (includeDefaults && fieldType().treeLevels() == 0) { // defaults only make sense if tree levels are not specified
builder.field(Names.TREE_PRESISION, DistanceUnit.METERS.toString(50));
}
if (includeDefaults || fieldType().strategyName() != Defaults.STRATEGY) {
builder.field(Names.STRATEGY, fieldType().strategyName());

View File

@ -27,6 +27,8 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.geo.GeoUtils;
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.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase;
@ -34,6 +36,7 @@ import org.elasticsearch.test.InternalSettingsPlugin;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import static org.elasticsearch.index.mapper.GeoPointFieldMapper.Names.IGNORE_Z_VALUE;
import static org.hamcrest.Matchers.containsString;
@ -517,4 +520,78 @@ public class GeoShapeFieldMapperTests extends ESSingleNodeTestCase {
assertThat(e.getMessage(), containsString("name cannot be empty string"));
}
public void testSerializeDefaults() throws Exception {
DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser();
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", "quadtree")
.endObject().endObject()
.endObject().endObject());
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
assertTrue(serialized, serialized.contains("\"precision\":\"50.0m\""));
assertTrue(serialized, serialized.contains("\"tree_levels\":21"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", "geohash")
.endObject().endObject()
.endObject().endObject());
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
assertTrue(serialized, serialized.contains("\"precision\":\"50.0m\""));
assertTrue(serialized, serialized.contains("\"tree_levels\":9"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", "quadtree")
.field("tree_levels", "6")
.endObject().endObject()
.endObject().endObject());
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
assertFalse(serialized, serialized.contains("\"precision\":"));
assertTrue(serialized, serialized.contains("\"tree_levels\":6"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", "quadtree")
.field("precision", "6")
.endObject().endObject()
.endObject().endObject());
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
assertTrue(serialized, serialized.contains("\"precision\":\"6.0m\""));
assertFalse(serialized, serialized.contains("\"tree_levels\":"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", "quadtree")
.field("precision", "6m")
.field("tree_levels", "5")
.endObject().endObject()
.endObject().endObject());
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
assertTrue(serialized, serialized.contains("\"precision\":\"6.0m\""));
assertTrue(serialized, serialized.contains("\"tree_levels\":5"));
}
}
public String toXContentString(GeoShapeFieldMapper mapper) throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
mapper.doXContentBody(builder, true, new ToXContent.MapParams(Collections.singletonMap("include_defaults", "true")));
return Strings.toString(builder.endObject());
}
}