根据产品文档《访问OSS非结构化数据》,自定义Extractor访问OSS。github项目详见:TextExtractor。
一、问题
该extractor在读取非结构化数据时,如果字段存在DateTime类型(例如:2019-10-27 19:44:36),会出现如下报错:
FAILED: ODPS-0123131:User defined function exception - Traceback:
java.lang.IllegalArgumentException
at java.sql.Date.valueOf(Date.java:143)
at com.aliyun.odps.udf.example.text.TextExtractor.textLineToRecord(TextExtractor.java:194)
at com.aliyun.odps.udf.example.text.TextExtractor.extract(TextExtractor.java:153)
at com.aliyun.odps.udf.ExtractorHandler.extract(ExtractorHandler.java:120)
根据堆栈,查看指定位置的代码:Date.valueOf(parts[i]),其中java.sql.Date.valueOf(),查询该函数官方文档,发现只能支持形如:"yyyy-[m]m-[d]d"的String类型参数。不支持时间部分。
二、解决方法
引入joda-time依赖
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10</version>
</dependency>
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
引入DateTimeFormat.forPattern(),指定日期格式对文本数据进行读取。
record.setDate(index, new Date(DateTime.parse(parts[i], DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).getMillis()));
三、结果验证
1. extractor项目打包生成jar包,通过odpscmd上传resource
add jar /Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jar
/Users/gary/big_data/odps/text_extractor/target/text_extractor-1.0-SNAPSHOT.jar,替换为本地实际jar包路径
另外,extractor使用了Joda-Time,需要额外添加第三方包。add jar /Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jar
/Users/gary/.m2/repository/joda-time/joda-time/2.10/joda-time-2.10.jar,替换为本地实际jar包路径
2. DDL建表,直接在odpscmd或者datastudio执行
CREATE EXTERNAL TABLE video_play_log
(
UUID STRING
,action STRING
,ip STRING
,time datetime
)
STORED BY 'me.gary.test.odps.examples.TextStorageHandler'
WITH SERDEPROPERTIES (
'odps.properties.rolearn'='acs:ram::<填写主账号uid>:role/aliyunodpsdefaultrole',
'delimiter'='^' --SERDEPROPERITES可以指定参数,这些参数会通过DataAttributes传递到Extractor代码中。
)
LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/<Bucket名称>/<目录名称>/'
USING 'text_extractor-1.0-SNAPSHOT.jar,joda-time-2.10.jar';
odps.properties.rolearn中的信息是RAM中AliyunODPSDefaultRole的ARN信息。通过RAM控制台中的角色详情获取。
OSS的连接格式为oss://oss-cn-shanghai-internal.aliyuncs.com/Bucket名称/目录名称/。按实际信息替换
3. 上传测试数据至oss bucket的指定目录,命名video_play_log.txt。
5c661071dba64d5080c91da085ff1073^视频播放页-点击-快进^27.17.94.60^2019-10-27 19:44:36
4. select外部表
select * from <project_name>.video_play_log;
读取结果: