具有 geo_shape 字段的文档无法反序列化?
Documents with a geo_shape field cannot be deserialized?
我的索引包含一个类型为 Nest.GeoShape 的字段。
------------
问题 #1 -- Kibana 将该字段显示为 "indexed = false",即使它是这样定义的(在创建索引期间使用 .MapFromAttributes())...
[ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
这是索引创建,以防出现问题...
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))))
------------
问题 #2 -- 当我进行查询时,返回的结果无法反序列化。
{"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."}
我预计这是因为我使用的是 Nest.GeoShape 而不是明确的 GeoShape 类型(如 EnvelopeGeoShape),但在我的情况下,每个文档都有不同的形状(5 个可能是圆形,3 个矩形, 2 个多边形和 74 个点)。
那么有没有办法可以进一步控制 Json 反序列化以检查类型并显式映射它以生成特定类型?或者(理想情况下)有没有办法让类型字段自动反序列化 "figure it out"?
好的,这是我找到的反序列化(问题 #2)的解决方案...
它需要编写 CustomCreationConverter 来处理可用于不同 GeoShape 类型的特定字段。这是积分示例:
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();
}
}
然后,为了使用此配置,我在 class...
中的字段本身上设置了一个装饰器
[JsonConverter(typeof(CustomNestGeoShapeConverter)), ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
这对我来说效果很好,但我仍然需要测试我是否可以搜索形状,即使 Kibana 认为该字段实际上没有索引(问题 #1)。
我的索引包含一个类型为 Nest.GeoShape 的字段。
------------
问题 #1 -- Kibana 将该字段显示为 "indexed = false",即使它是这样定义的(在创建索引期间使用 .MapFromAttributes())...
[ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
这是索引创建,以防出现问题...
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))))
------------
问题 #2 -- 当我进行查询时,返回的结果无法反序列化。
{"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."}
我预计这是因为我使用的是 Nest.GeoShape 而不是明确的 GeoShape 类型(如 EnvelopeGeoShape),但在我的情况下,每个文档都有不同的形状(5 个可能是圆形,3 个矩形, 2 个多边形和 74 个点)。
那么有没有办法可以进一步控制 Json 反序列化以检查类型并显式映射它以生成特定类型?或者(理想情况下)有没有办法让类型字段自动反序列化 "figure it out"?
好的,这是我找到的反序列化(问题 #2)的解决方案...
它需要编写 CustomCreationConverter 来处理可用于不同 GeoShape 类型的特定字段。这是积分示例:
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();
}
}
然后,为了使用此配置,我在 class...
中的字段本身上设置了一个装饰器 [JsonConverter(typeof(CustomNestGeoShapeConverter)), ElasticProperty(Index = FieldIndexOption.NotAnalyzed, Store = true, IncludeInAll = false)]
public Nest.GeoShape ElasticShape { get; set; }
这对我来说效果很好,但我仍然需要测试我是否可以搜索形状,即使 Kibana 认为该字段实际上没有索引(问题 #1)。