将json数组导入hive
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将json数组导入hive相关的知识,希望对你有一定的参考价值。
我正在尝试在hive中导入以下json
[{ “时间”:1521115600, “纬度”:44.3959, “经度”:26.1025, “高度”:53, “PM1”:21.70905, “PM25”:16.5, “PM10”:14.60085, “GAS1”:0, “气2”:0.12, “GAS3”:0 “gas4”:0, “温度”:空, “压力”:0, “湿度”:0, “噪声”:0},{ “时间”:1521115659, “纬度”:44.3959, “经度”:26.1025, “高度”:53, “PM1”:24.34045, “PM25”:18.5, “PM10”:16.37065, “GAS1”:0, “气2”:0.08,“GAS3 “:0,” gas4 “:0,” 温度 “:空,” 压力 “:0,” 湿度 “:0,” 噪声 “:0},{” 时间 “:1521115720,” 纬度 “:44.3959,” 经度“:26.1025,” 高度 “:53,” PM1 “:23.6826” PM25 “:18,” PM10 “:15.9282” GAS1 “:0,” 气2 “:0,1” GAS3 “:0”,gas4" : 0 “温度”:空, “压力”:0, “湿度”:0, “噪声”:0},{ “时间”:1521115779, “纬度”:44.3959, “经度”:26.1025, “高度”: 53, “PM1”:25.65615, “PM25”:19.5, “PM10”:17.25555, “GAS1”:0, “气2”:0.04, “GAS3”:0 “gas4”:0, “温度”:空, “压力”:0, “湿度”:0, “噪声”:0}]
CREATE TABLE json_serde (
s array<struct<time: timestamp, latitude: string, longitude: string, pm1: string>>)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES (
'mapping.value' = 'value'
)
STORED AS TEXTFILE
location '/user/hduser';
进口工作,但如果我尝试
Select * from json_serde;
它将从hadoop / user / hduser上的每个文档返回,只返回每个文件的第一个元素。
有一个关于使用json数组的好文档?
如果我可以建议你另一种方法只是将整个JSON
字符串作为String
数据类型加载到一个列到外部表中。唯一的限制是正确定义LINES TERMINATED BY
。例如如果你可以将每个json放在一行中,那么你可以创建如下表:
EG
CREATE EXTERNAL TABLE json_data_table (
json_data String
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY 'u0001' LINES TERMINATED BY '
' STORED AS TEXTFILE
LOCATION '/path/to/json';
使用Hive get_json_object
提取单个列。这个命令支持基本的xPath
,如查询到json字符串E.g.
如果json_data列具有低于JSON字符串
{"store":
{"fruit":[{"weight":8,"type":"apple"},{"weight":9,"type":"pear"}],
"bicycle":{"price":19.95,"color":"red"}
},
"email":"amy@only_for_json_udf_test.net",
"owner":"amy"
}
以下查询提取
SELECT get_json_object(json_data, '$.owner') FROM json_data_table;
返回amy
通过这种方式,您可以从表中提取每个json
元素作为列。
你有一组结构。你粘贴的只有一行。
如果你想看到所有的元素,you need to use inline
SELECT inline(s) FROM json_table;
或者,您需要重写文件,以使该数组中的每个对象都是其自己的文件行上的单个JSON对象
另外,我没有在您的数据中看到值字段,因此我不确定您在serde属性中的映射
您提供的JSON不正确。 JSON总是以一个开放的大括号"{"
开始,以一个结束的大括号"}"
结束。所以,首先要注意的是你的JSON是错误的。
您的JSON应该如下所示:
{"key":[{"key1":"value1","key2":"value2"},{"key1":"value1","key2":"value2""},{"key1":"value1","key2":"value2"}]}
并且,第二件事是您已将“时间”字段的数据类型声明为时间戳。但数据(1521115600)以毫秒为单位。时间戳数据类型需要格式为YYYY-MM-DD HH:MM:SS [.fffffffff]的数据。
因此,理想情况下,您的数据应采用以下格式:
{“myjson”:[{“time”:“1970-01-18 20:01:55”,“纬度”:44.3959,“经度”:26.1025,“海拔”:53,“pm1”:21.70905,“pm25 “:16.5,” PM10 “:14.60085,” GAS1 “:0,” 气2 “:0.12,” GAS3 “:0”,gas4 “:0,” 温度 “:空,” 压力 “:0,” 湿度“: 0,“噪音”:0},{“时间”:“1970-01-18 20:01:55”,“纬度”:44.3959,“经度”:26.1025,“海拔”:53,“pm1”:24.34045 “PM25”:18.5, “PM10”:16.37065, “GAS1”:0, “气2”:0.08, “GAS3”:0 “gas4”:0, “温度”:空, “压力”:0,”湿度“:0,”噪音“:0},{”时间“:”1970-01-18 20:01:55“,”纬度“:44.3959,”经度“:26.1025,”海拔“:53,”pm1 “:23.6826” PM25 “:18,” PM10 “:15.9282” GAS1 “:0,” 气2 “:0,1” GAS3 “:0”,gas4 “:0,” 温度 “:空,” 压力“: 0,“湿度”:0,“噪音”:0},{“时间”:“1970-01-18 20:01:55”,“纬度”:44.3959,“经度”:26.1025,“海拔”:53 “PM1”:25.65615, “PM25”:19.5, “PM10”:17.25555, “GAS1”:0, “气2”:0.04, “GAS3”:0 “gas4”:0, “温度”:NULL,”压力 “:0,” 湿度 “:0,” 噪声“:0}]}
现在,您可以使用查询从表中选择记录。
hive> select * from json_serde;
OK
[{"time":"1970-01-18 20:01:55","latitude":"44.3959","longitude":"26.1025","pm1":"21.70905"},{"time":"1970-01-18 20:01:55","latitude":"44.3959","longitude":"26.1025","pm1":"24.34045"},{"time":"1970-01-18 20:01:55","latitude":"44.3959","longitude":"26.1025","pm1":"23.6826"},{"time":"1970-01-18 20:01:55","latitude":"44.3959","longitude":"26.1025","pm1":"25.65615"}]
Time taken: 0.069 seconds, Fetched: 1 row(s)
hive>
如果希望以表格格式单独显示每个值,可以使用以下查询。
select b.* from json_serde a lateral view outer inline (a.myjson) b;
上述查询的结果如下:
+------------------------+-------------+--------------+-----------+--+
| b.time | b.latitude | b.longitude | b.pm1 |
+------------------------+-------------+--------------+-----------+--+
| 1970-01-18 20:01:55.0 | 44.3959 | 26.1025 | 21.70905 |
| 1970-01-18 20:01:55.0 | 44.3959 | 26.1025 | 24.34045 |
| 1970-01-18 20:01:55.0 | 44.3959 | 26.1025 | 23.6826 |
| 1970-01-18 20:01:55.0 | 44.3959 | 26.1025 | 25.65615 |
+------------------------+-------------+--------------+-----------+--+
美丽。不是吗?
快乐学习。
如果你不能使用更新你的输入文件格式,你可以直接导入spark并使用它,一旦数据完成后写回Hive表。
scala> val myjs = spark.read.format("json").option("path","file:///root/tmp/test5").load()
myjs: org.apache.spark.sql.DataFrame = [altitude: bigint, gas1: bigint ... 13 more fields]
scala> myjs.show()
+--------+----+----+----+----+--------+--------+---------+-----+--------+--------+----+--------+-----------+----------+
|altitude|gas1|gas2|gas3|gas4|humidity|latitude|longitude|noise| pm1| pm10|pm25|pressure|temperature| time|
+--------+----+----+----+----+--------+--------+---------+-----+--------+--------+----+--------+-----------+----------+
| 53| 0|0.12| 0| 0| 0| 44.3959| 26.1025| 0|21.70905|14.60085|16.5| 0| null|1521115600|
| 53| 0|0.08| 0| 0| 0| 44.3959| 26.1025| 0|24.34045|16.37065|18.5| 0| null|1521115659|
| 53| 0| 0.0| 0| 0| 0| 44.3959| 26.1025| 0| 23.6826| 15.9282|18.0| 0| null|1521115720|
| 53| 0|0.04| 0| 0| 0| 44.3959| 26.1025| 0|25.65615|17.25555|19.5| 0| null|1521115779|
+--------+----+----+----+----+--------+--------+---------+-----+--------+--------+----+--------+-----------+----------+
scala> myjs.write.json("file:///root/tmp/test_output")
或者你可以直接hive表
scala> myjs.createOrReplaceTempView("myjs")
scala> spark.sql("select * from myjs").show()
scala> spark.sql("create table tax.myjs_hive as select * from myjs")
以上是关于将json数组导入hive的主要内容,如果未能解决你的问题,请参考以下文章
Hive 将 JSON 数组中的每个 JSON 元素分解为行
错误代码:错误域 = NSCocoaErrorDomain 代码 = 3840“JSON 文本没有以数组或对象和允许未设置片段的选项开头。”