将json数组导入hive

时间:2018-03-15 14:51:51

标签: arrays json hadoop 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,” 温度”日期null, “压力”: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数组的好文档??

4 个答案:

答案 0 :(得分:0)

如果我可以建议您另一种方法,只需将整个JSON字符串作为String数据类型加载到外部表中。唯一的限制是正确定义LINES TERMINATED BY。例如如果你可以将每个json放在一行中,那么你可以创建如下表:

e.g。

CREATE EXTERNAL TABLE json_data_table (
    json_data String
    )   
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\u0001' LINES TERMINATED BY '\n' 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元素作为列。

答案 1 :(得分:0)

你有一系列结构。你粘贴的只有一行。

如果您想查看所有元素,you need to use inline

SELECT inline(s) FROM json_table;

或者,您需要重写文件,使得该数组中的每个对象都是文件自己行上的单个JSON对象

另外,我没有在您的数据中看到值字段,因此我不确定您在serde属性中的映射

答案 2 :(得分:0)

您提供的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”:[{ “时间”:“1970年1月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,” 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,” 温度 “:空,” 压力 “: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  |
+------------------------+-------------+--------------+-----------+--+

美丽。不是吗?

快乐学习。

答案 3 :(得分:0)

如果你不能使用更新你的输入文件格式,你可以直接导入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")