基于Tunnel SDK如何上传复杂类型数据到MaxCompute?首先介绍一下MaxCompute复杂数据类型:

复杂数据类型

MaxCompute采用基于ODPS2.0的SQL引擎,丰富了对复杂数据类型类型的支持。MaxCompute支持ARRAY, MAP, STRUCT类型,并且可以任意嵌套使用并提供了配套的内建函数。

类型 定义方法 构造方法
ARRAY array;array> array(1, 2, 3); array(array(1, 2); array(3, 4))
MAP map;map> map(“k1”, “v1”, “k2”, “v2”);map(1S, array(‘a’, ‘b’), 2S, array(‘x’, ‘y))
STRUCT struct;struct< field1:bigint, field2:array, field3:map> named_struct(‘x’, 1, ‘y’, 2);named_struct(‘field1’, 100L, ‘field2’, array(1, 2), ‘field3’, map(1, 100, 2, 200)

复杂类型构造与操作函数

返回类型 签名 注释
MAP map(K key1, V value1, K key2, V value2, ...) 使用给定key/value对建立map, 所有key类型一致,必须是基本类型,所有value类型一致,可为任意类型
ARRAY map_keys(Map m) 将参数中的map的所有key作为数组返回,输入NULL,返回NULL
ARRAY map_values(MAP m) 将参数中的map的所有value作为数组返回,输入NULL,返回NULL
int size(MAP) 取得给定MAP元素数目
TABLE explode(MAP) 表生成函数,将给定MAP展开,每个key/value一行,每行两列分别对应key和value
ARRAY array(T value1, T value2, ...) 使用给定value构造ARRAY,所有value类型一致
int size(ARRAY) 取得给定ARRAY元素数目
boolean array_contains(ARRAY a, value v) 检测给定ARRAY a中是否包含v
ARRAY sort_array(ARRAY) 对给定数组排序
ARRAY collect_list(T col) 聚合函数,在给定group内,将col指定的表达式聚合为一个数组
ARRAY collect_set(T col) 聚合函数,在给定group内,将col指定的表达式聚合为一个无重复元素的集合数组
TABLE explode(ARRAY) 表生成函数,将给定ARRAY展开,每个value一行,每行一列对应相应数组元素
TABLE (int, T) posexplode(ARRAY) 表生成函数,将给定ARRAY展开,每个value一行,每行两列分别对应数组从0开始的下标和数组元素
STRUCT struct(T1 value1, T2 value2, ...) 使用给定value列表建立struct, 各value可为任意类型,生成struct的field的名称依次为col1, col2, ...
STRUCT named_struct(name1, value1, name2, value2, ...) 使用给定name/value列表建立struct, 各value可为任意类型,生成struct的field的名称依次为name1, name2, ...
TABLE (f1 T1, f2 T2, ...) inline(ARRAY>) 表生成函数,将给定struct数组展开,每个元素对应一行,每行每个struct元素对应一列

Tunnel SDK 介绍

Tunnel 是 ODPS 的数据通道,用户可以通过 Tunnel 向 ODPS 中上传或者下载数据。
TableTunnel 是访问 ODPS Tunnel 服务的入口类,仅支持表数据(非视图)的上传和下载。

对一张表或 partition 上传下载的过程,称为一个session。session 由一或多个到 Tunnel RESTful API 的 HTTP Request 组成。
session 用 session ID 来标识,session 的超时时间是24小时,如果大批量数据传输导致超过24小时,需要自行拆分成多个 session。
数据的上传和下载分别由 TableTunnel.UploadSession 和 TableTunnel.DownloadSession 这两个会话来负责。
TableTunnel 提供创建 UploadSession 对象和 DownloadSession 对象的方法.

  • 典型表数据上传流程: 
    1) 创建 TableTunnel
    2) 创建 UploadSession
    3) 创建 RecordWriter,写入 Record
    4)提交上传操作
  • 典型表数据下载流程:
    1) 创建 TableTunnel
    2) 创建 DownloadSession
    3) 创建 RecordReader,读取 Record

基于Tunnel SDK构造复杂类型数据

代码示例:

  1. RecordWriter recordWriter = uploadSession.openRecordWriter(0);
  2. ArrayRecord record = (ArrayRecord) uploadSession.newRecord();
  3. // prepare data
  4. List arrayData = Arrays.asList(1, 2, 3);
  5. Map<String, Long> mapData = new HashMap<String, Long>();
  6. mapData.put("a", 1L);
  7. mapData.put("c", 2L);
  8. List<Object> structData = new ArrayList<Object>();
  9. structData.add("Lily");
  10. structData.add(18);
  11. // set data to record
  12. record.setArray(0, arrayData);
  13. record.setMap(1, mapData);
  14. record.setStruct(2, new SimpleStruct((StructTypeInfo) schema.getColumn(2).getTypeInfo(),
  15. structData));
  16. // write the record
  17. recordWriter.write(record);

从MaxCompute下载复杂类型数据

代码示例:

  1. RecordReader recordReader = downloadSession.openRecordReader(0, 1);
  2. // read the record
  3. ArrayRecord record1 = (ArrayRecord)recordReader.read();
  4. // get array field data
  5. List field0 = record1.getArray(0);
  6. List<Long> longField0 = record1.getArray(Long.class, 0);
  7. // get map field data
  8. Map field1 = record1.getMap(1);
  9. Map<String, Long> typedField1 = record1.getMap(String.class, Long.class, 1);
  10. // get struct field data
  11. Struct field2 = record1.getStruct(2);

运行实例

完整代码如下:

  1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import com.aliyun.odps.Odps;
  8. import com.aliyun.odps.PartitionSpec;
  9. import com.aliyun.odps.TableSchema;
  10. import com.aliyun.odps.account.Account;
  11. import com.aliyun.odps.account.AliyunAccount;
  12. import com.aliyun.odps.data.ArrayRecord;
  13. import com.aliyun.odps.data.RecordReader;
  14. import com.aliyun.odps.data.RecordWriter;
  15. import com.aliyun.odps.data.SimpleStruct;
  16. import com.aliyun.odps.data.Struct;
  17. import com.aliyun.odps.tunnel.TableTunnel;
  18. import com.aliyun.odps.tunnel.TableTunnel.UploadSession;
  19. import com.aliyun.odps.tunnel.TableTunnel.DownloadSession;
  20. import com.aliyun.odps.tunnel.TunnelException;
  21. import com.aliyun.odps.type.StructTypeInfo;
  22. public class TunnelComplexTypeSample {
  23. private static String accessId = "<your access id>";
  24. private static String accessKey = "<your access Key>";
  25. private static String odpsUrl = "<your odps endpoint>";
  26. private static String project = "<your project>";
  27. private static String table = "<your table name>";
  28. // partitions of a partitioned table, eg: "pt=\'1\',ds=\'2\'"
  29. // if the table is not a partitioned table, do not need it
  30. private static String partition = "<your partition spec>";
  31. public static void main(String args[]) {
  32. Account account = new AliyunAccount(accessId, accessKey);
  33. Odps odps = new Odps(account);
  34. odps.setEndpoint(odpsUrl);
  35. odps.setDefaultProject(project);
  36. try {
  37. TableTunnel tunnel = new TableTunnel(odps);
  38. PartitionSpec partitionSpec = new PartitionSpec(partition);
  39. // ---------- Upload Data ---------------
  40. // create upload session for table
  41. // the table schema is {"col0": ARRAY<BIGINT>, "col1": MAP<STRING, BIGINT>, "col2": STRUCT<name:STRING,age:BIGINT>}
  42. UploadSession uploadSession = tunnel.createUploadSession(project, table, partitionSpec);
  43. // get table schema
  44. TableSchema schema = uploadSession.getSchema();
  45. // open record writer
  46. RecordWriter recordWriter = uploadSession.openRecordWriter(0);
  47. ArrayRecord record = (ArrayRecord) uploadSession.newRecord();
  48. // prepare data
  49. List arrayData = Arrays.asList(1, 2, 3);
  50. Map<String, Long> mapData = new HashMap<String, Long>();
  51. mapData.put("a", 1L);
  52. mapData.put("c", 2L);
  53. List<Object> structData = new ArrayList<Object>();
  54. structData.add("Lily");
  55. structData.add(18);
  56. // set data to record
  57. record.setArray(0, arrayData);
  58. record.setMap(1, mapData);
  59. record.setStruct(2, new SimpleStruct((StructTypeInfo) schema.getColumn(2).getTypeInfo(),
  60. structData));
  61. // write the record
  62. recordWriter.write(record);
  63. // close writer
  64. recordWriter.close();
  65. // commit uploadSession, the upload finish
  66. uploadSession.commit(new Long[]{0L});
  67. System.out.println("upload success!");
  68. // ---------- Download Data ---------------
  69. // create download session for table
  70. // the table schema is {"col0": ARRAY<BIGINT>, "col1": MAP<STRING, BIGINT>, "col2": STRUCT<name:STRING,age:BIGINT>}
  71. DownloadSession downloadSession = tunnel.createDownloadSession(project, table, partitionSpec);
  72. schema = downloadSession.getSchema();
  73. // open record reader, read one record here for example
  74. RecordReader recordReader = downloadSession.openRecordReader(0, 1);
  75. // read the record
  76. ArrayRecord record1 = (ArrayRecord)recordReader.read();
  77. // get array field data
  78. List field0 = record1.getArray(0);
  79. List<Long> longField0 = record1.getArray(Long.class, 0);
  80. // get map field data
  81. Map field1 = record1.getMap(1);
  82. Map<String, Long> typedField1 = record1.getMap(String.class, Long.class, 1);
  83. // get struct field data
  84. Struct field2 = record1.getStruct(2);
  85. System.out.println("download success!");
  86. } catch (TunnelException e) {
  87. e.printStackTrace();
  88. } catch (IOException e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. }
  93.  
  94. 原文链接

如何使用Tunnel SDK上传/下载MaxCompute复杂类型数据的更多相关文章

  1. redisTemplate实现轻量级消息队列, 异步处理excel并实现腾讯云cos文件上传下载

    背景 公司项目有个需求, 前端上传excel文件, 后端读取数据.处理数据.返回错误数据, 最简单的方式同步处理, 客户端上传文件后一直阻塞等待响应, 但用户体验无疑很差, 处理数据可能十分耗时, 没 ...

  2. Android开发中使用七牛云存储进行图片上传下载

    Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...

  3. guacamole实现上传下载

    目录 1. 源码解读 2. 上传下载的核心代码 分析的入手点,查看websocket连接的frame 看到首先服务端向客户端发送了filesystem请求,紧接着浏览器向服务端发送了get请求,并且后 ...

  4. Java 客户端操作 FastDFS 实现文件上传下载替换删除

    FastDFS 的作者余庆先生已经为我们开发好了 Java 对应的 SDK.这里需要解释一下:作者余庆并没有及时更新最新的 Java SDK 至 Maven 中央仓库,目前中央仓库最新版仍旧是 1.2 ...

  5. RxHttp 完美适配Android 10/11 上传/下载/进度监听

    1.前言 随着Android 11的正式发布,适配Android 10/11 分区存储就更加的迫切了,因为Android 11开始,将强制开启分区存储,我们就无法再以绝对路径的方式去读写非沙盒目录下的 ...

  6. Struts的文件上传下载

    Struts的文件上传下载 1.文件上传 Struts2的文件上传也是使用fileUpload的组件,这个组默认是集合在框架里面的.且是使用拦截器:<interceptor name=" ...

  7. 基于Spring Mvc实现的Excel文件上传下载

    最近工作遇到一个需求,需要下载excel模板,编辑后上传解析存储到数据库.因此为了更好的理解公司框架,我就自己先用spring mvc实现了一个样例. 基础框架 之前曾经介绍过一个最简单的spring ...

  8. Android okHttp网络请求之文件上传下载

    前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...

  9. 用Canvas+Javascript FileAPI 实现一个跨平台的图片剪切、滤镜处理、上传下载工具

    直接上代码,其中上传功能需要自己配置允许跨域的文件服务器地址~ 或者将html文件贴到您的站点下同源上传也OK. 支持: 不同尺寸图片获取. 原图缩小放大. 原图移动. 选择框大小改变. 下载选中的区 ...

随机推荐

  1. Nacos v0.7.0:对接CMDB,实现基于标签的服务发现能力

    Nacos近期发布了0.7.0版本,该版本支持对接第三方CMDB获取CMDB数据.使用Selector机制来配置服务的路由类型.支持单机模式使用MySQL数据库.上线Node.js客户端,并修复了一些 ...

  2. Ubuntu下github pages+hexo搭建自己的博客

    hexo 是一个基于Node.js的静态博客程序,可以方便的生成静态网页托管在github上.Hexo简单优雅, 而且风格多变, 适合搭建个人博客,而且支持多平台的搭建. 平台 Ubuntu14.04 ...

  3. HDU - 1560 DNA sequence

    给你最多8个长度不超过5的DNA系列,求一个包含所有系列的最短系列. 迭代加深的经典题.(虽然自己第一次写) 定一个长度搜下去,搜不出答案就加深大搜的限制,然后中间加一些玄学的减枝 //Twenty ...

  4. 024_mysql应用

    初级照片位置:https://www.cnblogs.com/a276665092/gallery/image/277598.html 好丑啊 ,这怎么改啊!!!! 高级:https://www.cn ...

  5. Linux使用crontab定时执行Python脚本清理日志

    Linux中,周期执行的任务一般由crond这个守护进程来处理.cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间.crond的配置文件称为"crontab", ...

  6. 8.关于ActiveMQ、RocketMQ、RabbitMQ、Kafka一些总结和区别

    这是一篇分享文 转自:http://www.cnblogs.com/williamjie/p/9481780.html  尊重原作,谢谢 消息队列 为什么写这篇文章? 博主有两位朋友分别是小A和小B: ...

  7. git使用中的问题

    一.github ssh_exchange_identification: read: Connection reset by peer 和电脑环境有关,检查防火墙关了没有,是不是杀毒软件.安全卫士的 ...

  8. spring-data-JPA repository自定义方法规则

    一.自定义方法的规则 Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find,findBy,read,readBy,get,getBy,然后对剩下的部分进行解 ...

  9. 【学术篇】状态压缩动态规划——POJ3254/洛谷1879 玉米田Corn Field

    我要开状压dp的坑了..直播从入门到放弃系列.. 那就先拿一道状压dp的水题练练手吧.. 然后就找到了这一道..这道题使我清醒地认识到阻碍我的不是算法,而是视力= = 传送门: poj:http:// ...

  10. Java虚拟机笔记

    Java内存区域划分 1.程序计数器 线程私有,当前线程执行的行号指示器,指向当前线程执行的虚拟机字节码地址,线程的恢复,跳转等都需要用到它 2.Java虚拟机栈 线程私有,虚拟机栈描述的是Java内 ...