Java Hive UDTF 将WKT格式的Geomotry转换成GeoJSON

Java Hive UDTF 将WKT格式的Geomotry转换成GeoJSON

背景知识

WKT(Well-known text)是一种文本标记语言,用于表示矢量几何对象、空间参照系统及空间参照系统之间的转换。它的二进制表示方式,亦即WKB(well-known-binary)则胜于在传输和在数据库中存储相同的信息。
GeoJSON是一种对各种地理数据结构进行编 码的格式,可以表示几何、特征或者特征集合。

WTK
点 POINT(6 10)
线 LINESTRING(44 4,11 44,33 25)
面 POLYGON((1 1,2 2,3 3,4 4,5 5,1 1),(11 11,2 13,34 43,34 42,52 52,11 11))
多点 MULTIPOINT(44 4,11 44,33 25)
多线 MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))
多面 MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))
几何集合 GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))
对应geojson
点 {“type”:“Point”,“coordinates”:[6,10]}
线 {“type”:“LineString”,“coordinates”:[[44, 4],[11, 44],[33, 25]]}
面 {“type”:“Polygon”,“coordinates”:[[[1, 1],[2, 2],[3, 3],[4, 4],[5, 5],[1, 1]],[[11, 11],[2, 13],[34, 43],[34, 42],[52, 52],[11, 11]]]}
多点 {“type”:“MultiPoint”,“coordinates”:[[44, 4],[11, 44],[33, 25]]}
多线 {“type”:“MultiLineString”,“coordinates”:[[[3, 4],[10, 50],[20, 25]],[[-5, -8],[-10, -8],[-15, -4]]}
多面 {“type”:“MultiPolygon”,“coordinates”:[[[3, 4],[10, 50],[20, 25]],[[-5, -8],[-10, -8],[-15, -4]]]}
几何集合 {“type”:“FeatureCollection”,“features”:[{“type”:“Feature”,“geometry”:{“type”:“Point”,“coordinates”:[4,6]},},{“type”:“Feature”,“geometry”:{“type”:“LineString”,“coordinates”:[[[4,6],[7,10]]}]}

具体需求

目前MULTIPOLYGON不能直接转成geojson,主要是业务方不能处理多面,需要对多面进行拆分成多个Polygon ,具体到hive数据就是实现udtf对这种多面类型的数据进行解析处理,拆分成多行一行代表一个Polygon。

解决方案

方法一:调研库函数直接封装进行处理:比如 vividsolutions jts包 进行处理
vividsolutions比较强大,其实现原理如下:
Geometry类作为基础数据类型,单点、单线、单面都继承Geometry去实现,同时定义了一个GeometryCollection来实现Geometry 底层用Geometry类型的数组数据结果进行存储,多点、多线、多面都继承自GeometryCollection ,基本上解析后只需要对类型进行判断,然后根据类型进行层层处理 比如:多面类型里面有多个面,对多面进行循环解析就可以了。
如下代码片段

// 如下传如一个 Geometry 基础类,这里会利用java多态进行判断 
public static JSONObject parsePolygon2Geojson(Geometry geom) throws ParseException {
   
   JSONObject jsonObject = new JSONObject();
   String type = geom.getGeometryType();
   jsonObject.put("type", geom.getGeometryType());
   if ("MultiPolygon".equalsIgnoreCase(type)) {
   
     JSONArray coordJson = new JSONArray();
     //geom 实际上底层数据结构是数组,可以从中获取单个Polygon
     for (int i = 0; i < geom.getNumGeometries(); i++) {
   
       // polygon
       coordJson.add(parsePolygon
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的 Java 代码示例,演示如何实现一个 Hive UDTF 函数。 ```java import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; import org.apache.hadoop.hive.ql.exec.UDFType; import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.StructField; import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; import org.apache.hadoop.io.Text; import java.util.ArrayList; import java.util.List; @UDFType(deterministic = true, stateful = false) public class MyUDTF extends GenericUDTF { private StringObjectInspector inputOI = null; @Override public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException { if (args.length != 1) { throw new UDFArgumentLengthException("MyUDTF takes only one argument"); } if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE || !args[0].getTypeName().equals("string")) { throw new UDFArgumentTypeException(0, "Argument 1 must be a string"); } inputOI = (StringObjectInspector) args[0]; // Define the output column names and types List<String> fieldNames = new ArrayList<String>(); List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(); fieldNames.add("word"); fieldOIs.add(PrimitiveObjectInspectorFactory.writableStringObjectInspector); return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs); } @Override public void process(Object[] args) throws HiveException { String input = inputOI.getPrimitiveJavaObject(args[0]).toString(); String[] words = input.split(" "); for (String word : words) { Text t = new Text(word); forward(new Object[]{t}); } } @Override public void close() throws HiveException { // do nothing } } ``` 在上面的代码中,我们定义了一个名为 `MyUDTF` 的类,继承了 Hive 的 `GenericUDTF` 类,并重写了其中的 `initialize`、`process` 和 `close` 方法。 其中,`initialize` 方法用于初始化 UDTF 函数,我们在这里检查函数的输入参数是否符合要求,并定义了函数的输出列名和类型;`process` 方法用于处理每一行输入数据,并将结果输出;`close` 方法用于清理资源。 具体实现中,我们将输入字符串按空格分割成单词,并将每个单词作为一个输出行返回。在 `forward` 方法中,我们将每个单词封装成一个 `Text` 类型的对象,并通过 `Object[]` 数组的形式传递给 Hive 引擎。 需要注意的是,在类上我们添加了 `@UDFType` 注解,指定了该 UDTF 函数是确定性的(即相同的输入一定产生相同的输出)和无状态的(即不依赖于之前的输入状态)。这个注解可以让 Hive 引擎更好地优化查询执行计划。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

house.zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值