使用场景
场景一 (博主实际使用场景)
- 因为公司近期涉及埋点数据的业务逻辑,对于扩展字进行补充因此采用map数据类型存储扩展字段.
场景二 (其他业务场景)
-
场景2.1
我的项目里,生成的一个中间表,为了优化性能,里面有一列最好是个数组,因为如果把数组打散,每行上存一个元素,会因为其他列的重复导致数据量爆炸。首先想从上游表中生成这个数组,搜索半天文档,发现唯一的方式是把源数据列先转STRING,再用wm_concat聚合,再用split函数打散成ARRAY ,这样原来类型信息丢了,不过STRING似乎也能用,好,继续。后面的运算有个地方需要取数组最后一个元素,试图用数组下标配合size函数,my_array[size(my_array)], 发现报告错误,下标必须是常量,可是我的数组不是定长的,看看有没有函数能反转数组呢?没有!最后不得不放弃使用数组。。。 -
场景2.2
我的任务是为每个广告生成一个曲线,代表随着广告商的出价由低到高,预计的impression, click次数的曲线。最自然的表达是有个数据结构,里面存着出价,impression次数,click次数。可是ODPS不支持这样的用法,只好encode成一个字符串,每次操作先编码,再解码。好麻烦,效率也很差,可是没有办法。。。
工具
-
作者使用的阿里云maxcompute工具,数据源在ES 使用阿里云数据集成脚本方式实现数据同步.备注因为数据源是String类型,阿里云的同步工具不支持将string 转为 map 数据类型.因此在数据同步过程中也就是ods层采用String类型进行数据存储,后续处理采用map数据类型. 使用Sqoop同步数据的话采用的方式作者一致
-
如果你采用dataX的支持在序列换过程中将String类型转化为Map数据类型
建议格式
-
扩展字段必须用String 同步源数据格式为 (KaTeX parse error: Expected 'EOF', got '#' at position 7: aaa:11#̲bbb:22#KaTeX parse error: Expected 'EOF', got '#' at position 13: key1:[{},{}]#̲key2:[{},{}])
- 1.1 $的含义是用来区分扩展字段 (提高易读性)
- 1.2 # 用来切分文本数据
- 1.3 $key1":[{},{}] 这种复杂的数据格式 需要单独处理
- 1.4 后续数据格式的处理使用map字段数据类型
样例场景
- 建表语句
CREATE TABLE test_employee ( bar MAP<STRING,STRING>);
- 导入数据
数据一
insert into TABLE test_employee
select str_to_map('"$aaa":"11"#"$bbb":"22"#"$key1":[{"shopId":"9033871623535131526","vehicleNum":"1"},{"shopId":"9033871623535131526","vehicleNum":"1"}]#"$key2":[{"shopId":"9033871623535131526","vehicleNum":"2"},{"shopId":"9033871623535131526","vehicleNum":"2"}]',"#",":");
数据二
insert into TABLE test_employee
select str_to_map('$aaa:11#$bbb:22#$key1:[{"shopId":"9033871623535131526","vehicleNum":"1"},{"shopId":"9033871623535131526","vehicleNum":"1"}]',"#",":");
- 执行SQL (想知道结果的输出一定要自己动手、做人不可以懒啊)
select aa.user_id,bb.col,rr.shopId,rr.vehicleNum
from
(SELECT user_id
--arg3
,split(regexp_replace(regexp_extract(
arg3,
'^\\[(.+)\\]$',1),
'\\}\\,\\{', '}||{'),'\\|\\|' -- odps 格式
) as arg3_str
-- '\\}\\,\\{', '}||{') 第三方云格式
FROM prod_es_user_behavior_data_integration
WHERE dt = 20200412
and arg3 is not null
and user_id in ("677132")
) aa
-- 原因 1
-- 对于 [{},{},{}] 这种格式是无法直接进行解析 需要进行单独处理
-- regexp_replace,regexp_extract 这两种函数的使用要清楚
-- 上面的匹配原则可以通用、注意odps 与 第三方云平台的区别。
-- 不建议采用自定义函数处理上述结果、原因就是效率低
lateral view explode(aa.arg3_str) bb as col
-- 原因 2 实现行转列
-- 使用json_tuple 对key 进行解析
lateral view json_tuple(bb.col,'shopId','vehicleNum') rr as shopId,vehicleNum
;
- size函数 用来查看key的个数,返回的是int类型
select size(bar) from test_employee;
- map_keys 函数 用来查看key 返回array类型
select map_keys(bar) from test_employee;
- map_values 函数 用来查看值 返回array类型
select map_values(bar) from test_employee;
- str__to_map(str_,Delimiter1,Delimiter2)
Delimiter1 切分文本(文本的含义代表字符串的值)
Delimiter2 切分KV
样例1
select str_to_map('"aaa":"11"&"bbb":"22"', ':');
错误输出 {"11"&"bbb":NULL, "22":NULL, "aaa":NULL}
样例2
select str_to_map('"aaa":"11"&"bbb":"22"', '&',':');
正确输出 {"aaa":"11", "bbb":"22"}
样例3
select str_to_map('"aaa":"11","bbb":"22","key1":"[{},{},{}]"', ',',':'); -- {"aaa":"11", "bbb":"22", "key1":"[{}, {}:NULL, {}]":NULL}
错误输出: 复杂的数据格式无法输出
特殊场景用法
- 注意事项 1
- 注意事项 2
-
注意事项 3
- 采用 lateral view + json__tuple 对于key进行解析,备注json_object 与 json_tuple 的区别就是可以解析 可以解析多个字段还是解析一个字段。
- explode (array) 输入是数组 输出是行 一行转多行
福利分享
- 复杂的数据类型可以进行嵌套 (扩展部分可以滤过)
- 低频函数