使用 jsonserde 在配置单元中加载复杂的 json
Load complex json in hive using jsonserde
我正在尝试在配置单元中构建一个 table 以跟随 json
{
"business_id": "vcNAWiLM4dR7D2nwwJ7nCA",
"hours": {
"Tuesday": {
"close": "17:00",
"open": "08:00"
},
"Friday": {
"close": "17:00",
"open": "08:00"
}
},
"open": true,
"categories": [
"Doctors",
"Health & Medical"
],
"review_count": 9,
"name": "Eric Goldberg, MD",
"neighborhoods": [],
"attributes": {
"By Appointment Only": true,
"Accepts Credit Cards": true,
"Good For Groups": 1
},
"type": "business"
}
我可以使用以下 DDL 创建 table,但是在查询 table 时出现异常。
CREATE TABLE IF NOT EXISTS business (
business_id string,
hours map<string,string>,
open boolean,
categories array<string>,
review_count int,
name string,
neighborhoods array<string>,
attributes map<string,string>,
type string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.JsonSerde';
检索数据时的异常是 "ClassCast:Cant cast jsoanarray to json object"。此 json 的正确架构是什么?有没有什么可以帮助我为给定的 json 生成正确的模式以与 jsonserde 一起使用?
在我看来,问题是 hours
,您将其定义为 hours map<string,string>
,但应该是 map<string,map<string,string>
。
有一个工具可用于根据您的 JSON 数据自动生成配置单元 table 定义:https://github.com/quux00/hive-json-schema
但您可能需要调整它,因为当遇到 JSON 对象({} 之间的任何对象)时,该工具不知道是将其转换为配置单元 map
还是 struct
。
根据您的数据,该工具为我提供了以下信息:
CREATE TABLE x (
attributes struct<accepts credit cards:boolean,
by appointment only:boolean, good for groups:int>,
business_id string,
categories array<string>,
hours map<string:struct<close:string, open:string>
name string,
neighborhoods array<string>,
open boolean,
review_count int,
type string
)
但您似乎想要这样的东西:
CREATE TABLE x (
attributes map<string,string>,
business_id string,
categories array<string>,
hours map<string,struct<close:string, open:string>>,
name string,
neighborhoods array<string>,
open boolean,
review_count int,
type string
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS TEXTFILE;
hive> load data local inpath 'json.data' overwrite into table x;
hive> Table default.x stats: [numFiles=1, numRows=0, totalSize=416,rawDataSize=0]
OK
hive> select * from x;
OK
{"accepts credit cards":"true","by appointment only":"true",
"good for groups":"1"}
vcNAWiLM4dR7D2nwwJ7nCA
["Doctors","Health & Medical"]
{"tuesday":{"close":"17:00","open":"08:00"},
"friday":{"close":"17:00","open":"08:00"}}
Eric Goldberg, MD ["HELLO"] true 9 business
Time taken: 0.335 seconds, Fetched: 1 row(s)
hive>
一些注意事项:
- 请注意,我使用了不同的 JSON SerDe,因为我的系统上没有您使用的那个。我用了 this one,我更喜欢它,因为它是我写的。但是 create 语句应该与其他 serde 一样工作。
- 您可能希望将其中一些映射转换为结构,因为它们可能更便于查询。例如,
attributes
可以是一个结构,但您需要将其中的名称映射为 space,例如 accepts credit cards
。我的 SerDe 允许将 json 属性映射到不同的配置单元列名称。这也是需要的,然后 JSON 使用作为配置单元关键字的属性,如 'timestamp' 或 'create'.
我正在尝试在配置单元中构建一个 table 以跟随 json
{
"business_id": "vcNAWiLM4dR7D2nwwJ7nCA",
"hours": {
"Tuesday": {
"close": "17:00",
"open": "08:00"
},
"Friday": {
"close": "17:00",
"open": "08:00"
}
},
"open": true,
"categories": [
"Doctors",
"Health & Medical"
],
"review_count": 9,
"name": "Eric Goldberg, MD",
"neighborhoods": [],
"attributes": {
"By Appointment Only": true,
"Accepts Credit Cards": true,
"Good For Groups": 1
},
"type": "business"
}
我可以使用以下 DDL 创建 table,但是在查询 table 时出现异常。
CREATE TABLE IF NOT EXISTS business (
business_id string,
hours map<string,string>,
open boolean,
categories array<string>,
review_count int,
name string,
neighborhoods array<string>,
attributes map<string,string>,
type string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.JsonSerde';
检索数据时的异常是 "ClassCast:Cant cast jsoanarray to json object"。此 json 的正确架构是什么?有没有什么可以帮助我为给定的 json 生成正确的模式以与 jsonserde 一起使用?
在我看来,问题是 hours
,您将其定义为 hours map<string,string>
,但应该是 map<string,map<string,string>
。
有一个工具可用于根据您的 JSON 数据自动生成配置单元 table 定义:https://github.com/quux00/hive-json-schema
但您可能需要调整它,因为当遇到 JSON 对象({} 之间的任何对象)时,该工具不知道是将其转换为配置单元 map
还是 struct
。
根据您的数据,该工具为我提供了以下信息:
CREATE TABLE x (
attributes struct<accepts credit cards:boolean,
by appointment only:boolean, good for groups:int>,
business_id string,
categories array<string>,
hours map<string:struct<close:string, open:string>
name string,
neighborhoods array<string>,
open boolean,
review_count int,
type string
)
但您似乎想要这样的东西:
CREATE TABLE x (
attributes map<string,string>,
business_id string,
categories array<string>,
hours map<string,struct<close:string, open:string>>,
name string,
neighborhoods array<string>,
open boolean,
review_count int,
type string
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
STORED AS TEXTFILE;
hive> load data local inpath 'json.data' overwrite into table x;
hive> Table default.x stats: [numFiles=1, numRows=0, totalSize=416,rawDataSize=0]
OK
hive> select * from x;
OK
{"accepts credit cards":"true","by appointment only":"true",
"good for groups":"1"}
vcNAWiLM4dR7D2nwwJ7nCA
["Doctors","Health & Medical"]
{"tuesday":{"close":"17:00","open":"08:00"},
"friday":{"close":"17:00","open":"08:00"}}
Eric Goldberg, MD ["HELLO"] true 9 business
Time taken: 0.335 seconds, Fetched: 1 row(s)
hive>
一些注意事项:
- 请注意,我使用了不同的 JSON SerDe,因为我的系统上没有您使用的那个。我用了 this one,我更喜欢它,因为它是我写的。但是 create 语句应该与其他 serde 一样工作。
- 您可能希望将其中一些映射转换为结构,因为它们可能更便于查询。例如,
attributes
可以是一个结构,但您需要将其中的名称映射为 space,例如accepts credit cards
。我的 SerDe 允许将 json 属性映射到不同的配置单元列名称。这也是需要的,然后 JSON 使用作为配置单元关键字的属性,如 'timestamp' 或 'create'.