空间数据类型转化——geometry转geoJson转geoShape
2016-07-05 17:40
621 查看
在SqlServer等结构化的数据库中通常使用geometry 或者是 geoGraphy 。在数据中的类型如下:
.NET对其操作 通过使用EF中的DbGeometry类型进行映射,并且包含对其的多种属性和操作。基本可以满足我们通用的需求。
在EF中,该类型的定义如下:
这虽然满足,.net程序,对于空间数据的基本使用和操作。但是由于目前我们使用的数据存储服务器为ElasticSearch。其中定义空间数据包含两种类型,分别是geoShape和geoPoint两种类型。
我们想要实现数据库中空间类型 和 elasticsearch中空间类型的转化显得非常困难。因为两种类型的结构和形式完全不同。
查找多方资料,终于知道ElasticSearch是一种geoJson类型的。因此需要先将geometry转成 geoJson ,geoJson再转成geoShape。
下面是转化的步骤:
最后在已安装的包中查看如下:
需要注意的是,geoJson依赖的newtnsoft.json的版本是7.0以上,所以很有可能和当前项目冲突。可以通过修改配置文件的版本进行解决。
调用的代码如下:
传入参数是一个DBGeometry类型的,然后输出的值是一个geoJson抽象类的一个具体实现类,因此这里返回的是一个动态类型。也可使用GeoJsonObject类型。
非常幸运,我们做到这一步,基本就可以直接导入到ElasticSearch中去了,因为geoJson的格式和geoShape的格式是一摸一样的。
下面是bulk代码
通过以上步骤,就解决了ES中geoShape空间数据导入的难题。不过geometry到geojson的转化还是有些不好,需要人工去解析和转化。期待更好的解决方案!
.NET对其操作 通过使用EF中的DbGeometry类型进行映射,并且包含对其的多种属性和操作。基本可以满足我们通用的需求。
在EF中,该类型的定义如下:
这虽然满足,.net程序,对于空间数据的基本使用和操作。但是由于目前我们使用的数据存储服务器为ElasticSearch。其中定义空间数据包含两种类型,分别是geoShape和geoPoint两种类型。
我们想要实现数据库中空间类型 和 elasticsearch中空间类型的转化显得非常困难。因为两种类型的结构和形式完全不同。
查找多方资料,终于知道ElasticSearch是一种geoJson类型的。因此需要先将geometry转成 geoJson ,geoJson再转成geoShape。
下面是转化的步骤:
1.安装NuGet包 geoJson.net
在需要使用geoJson类型的项目,右键点击“管理NuGet程序包”,搜索geoJson.net,出现的结果中选择geoJson.net 选择安装即可。最后在已安装的包中查看如下:
需要注意的是,geoJson依赖的newtnsoft.json的版本是7.0以上,所以很有可能和当前项目冲突。可以通过修改配置文件的版本进行解决。
2.geometry 转化成geoJSON
具体转化的代码如下,需要引用geoJson才可使用哦using System; using System.Data.Entity.Spatial; using System.Linq; using GeoJSON.Net.Geometry; using Newtonsoft.Json; namespace Jurassic.Sooil.Model.IOModel { public class GisUtil { /** * 将WKT文本字符串转换为ES中的GeoShape字符串格式 * @param wkt * @return * @throws ParseException */ public static string GetEsGeoTextFromWkt(DbGeometry geo) { string result = null; string coordinates = null; var type = geo.SpatialTypeName.ToLower(); if (type.Equals("point")) { coordinates = GetEsPointText(geo); } else { coordinates = GetEsMultiPointText(geo); } result += "{\"type\" :\"" + type + "\"" + ", \"coordinates\" :" + coordinates + "}"; return result; } /** * 通过MultiPoint对象拼接中括号表示的字符串 * @param multiPoint * @return */ private static String GetEsMultiPointText(DbGeometry polygon) { var wkt = polygon.WellKnownValue.WellKnownText; var startIndex = wkt.IndexOf('('); var endIndex = wkt.LastIndexOf(')'); var coordinates = wkt.Substring(startIndex, endIndex - startIndex + 1); var coods = coordinates.Replace('(', '[').Replace(')', ']').Split(','); var result = ""; foreach (var cood in coods) { var s= cood.TrimStart().Replace(' ', ','); result += string.Format("[" + s + "],"); } result= result.Remove(result.Length - 1); return result; } /** * 通过Point对象拼接中括号表示的字符串 * @param point * @return */ public static String GetEsPointText(DbGeometry point) { return "[" + point.XCoordinate + "," + point.YCoordinate + "]"; } public static dynamic GetGeoJson(DbGeometry geo) { var geoText = GetEsGeoTextFromWkt(geo); var type = geo.SpatialTypeName.ToLower(); switch (type) { case "point": return JsonConvert.DeserializeObject<Point>(geoText); case "polygon": return JsonConvert.DeserializeObject<Polygon>(geoText); case "multipolygon": return JsonConvert.DeserializeObject<MultiPolygon>(geoText); case "multilinestring": return JsonConvert.DeserializeObject<MultiLineString>(geoText); default: return null; } } } }
调用的代码如下:
Spatial =GisUtil.GetGeoJson(DbGeometry.FromText("POLYGON ((125.718299865723 45.7559700012207, 125.700149536133 45.761962890625, 125.68383026123 45.7523498535156, 125.672470092773 45.7415008544922, 125.667694091797 45.729377746582, 125.664573669434 45.7161026000977, 125.681015014648 45.7145957946777, 125.71363067627 45.7338333129883, 125.716812133789 45.7426528930664, 125.721588134766 45.7547760009766, 125.718299865723 45.7559700012207))", 4326))
传入参数是一个DBGeometry类型的,然后输出的值是一个geoJson抽象类的一个具体实现类,因此这里返回的是一个动态类型。也可使用GeoJsonObject类型。
3.geoJson转化成geoShape
也就是说如何把转化后的数据导入到ElasticSearch中去。非常幸运,我们做到这一步,基本就可以直接导入到ElasticSearch中去了,因为geoJson的格式和geoShape的格式是一摸一样的。
下面是bulk代码
/// <summary> /// 修改数据模型模型后,导入ES的数据 /// </summary> /// <param name="docs"></param> /// <param name="type"></param> /// <returns></returns> public async Task<string> Index(List<T> docs, string type) { var serializer = new JsonNetSerializer(); var bulkJson = new BulkBuilder(serializer) .BuildCollection(docs, (builder, doc) => builder.Index(doc) ); return await Bulk(bulkJson, type); } /// <summary> /// bulk操作,根据指定的索引和类型 /// </summary> /// <param name="bulkJson"></param> /// <param name="type"></param> /// <returns></returns> public async Task<string> Bulk(string bulkJson, string type) { if (bulkJson == null) return "索引文档为空"; string bulkCommand = new BulkCommand(EsIndex, type); var result = await esClient.Post(bulkCommand, bulkJson); return result; }
4.插入结果查询
在sense中查询,插入的空间数据如下图:通过以上步骤,就解决了ES中geoShape空间数据导入的难题。不过geometry到geojson的转化还是有些不好,需要人工去解析和转化。期待更好的解决方案!
相关文章推荐
- JSBinding / Code Snippets
- javascript内建对象String,Array,Math,Date()
- BZOJ_1027_[JSOI2007]_合金_(计算几何+Floyd求最小环)
- javascript单例模式
- 动态拼接json数组
- js自定义事件及事件交互原理概述(二)
- Javascript快速入门(下篇)
- js页面跳转的问题(跳转到父页面、最外层页面、本页面)
- js的调试详解
- JS正则表达式 替换括号,尖括号等
- JSP中的编码设置
- jvm jstat 命令使用
- 在jsp页面上做判断
- ZTree学习(一):一般使用,一次性加载数据
- js与jsp之间取值问题
- FastJson详解
- js自定义事件及事件交互原理概述(一)
- Handlebars 和 SeaJS 的结合使用
- js中this理解
- javascript onfocus()和onselect()方法区别