My index contains a field that is of type Nest.GeoShape.
Problem #1 -- Kibana shows that field as "indexed = false" even though it has been defined like this (with .MapFromAttributes() during index creation)...
[ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
here's the index creation, in case that's the problem...
client.CreateIndex(c => c
.Index(indexName)
.InitializeUsing(set)
.AddMapping<ItemSearchable>(m => m
.MapFromAttributes()
.Properties(props => props
.GeoShape(x => x
.Name(n => n.ElasticShape)
.Tree(GeoTree.Geohash)
.TreeLevels(9)
.DistanceErrorPercentage(0.025))))
Problem #2 -- When I do a query, the results that come back fail to deserialize.
{"Could not create an instance of type Nest.GeoShape. Type is an interface or abstract class and cannot be instantiated. Path 'hits.hits[0]._source.elasticShape.coordinates', line 10, position 19."}
I expect it's because I'm using Nest.GeoShape rather than an explicit GeoShape type (like EnvelopeGeoShape), but in my case, each document will have a different shape (5 might be circles, 3 rectangles, 2 polygons, and 74 points).
So is there a way I can further control the Json Deserialization to check the type and explicitly map it to generate a particular type? Or (ideally) is there a way to simply let the deserialization "figure it out" from the type field automatically?
Okay, here's what I found as a solution to the Deserialization (Problem #2)...
It requires a CustomCreationConverter to be written to handle the specific fields available for the different GeoShape types. Here's a sample for points:
public class CustomNestGeoShapeConverter : CustomCreationConverter<Nest.GeoShape>
{
public override Nest.GeoShape Create(Type objectType)
{
return null;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if(token == null) return null;
switch (token["type"].ToString())
{
case "point":
{
var coords = new List<double>();
coords.Add(Double.Parse(token["coordinates"][0].ToString()));
coords.Add(Double.Parse(token["coordinates"][1].ToString()));
return new Nest.PointGeoShape() { Coordinates = coords };
}
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then, to use this configuration, I set up a decorator on the field itself within my class...
[JsonConverter(typeof(CustomNestGeoShapeConverter)), ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
This is working great for me now, but I still need to test whether I can search against the shape even if Kibana thinks the field is not actually indexed (Problem #1).