【问题标题】:issue with Hive Serde dealing nested structsHive Serde 处理嵌套结构的问题
【发布时间】:2016-04-04 00:27:12
【问题描述】:

我正在尝试使用 Json serde 加载具有嵌套结构的大量 json 数据以进行配置。在嵌套结构中,一些字段名称以 $ 开头。我正在使用SerDeproperties 映射配置单元文件名称,但是当我查询表时,在以$ 开头的字段中为空,尝试使用不同的语法,但没有运气。

示例 JSON:

{
    "_id" : "319FFE15FF90",
    "SomeThing" : 
    {
            "$SomeField"     : 22,
            "AnotherField"   : 2112,
            "YetAnotherField":    1
    }
 . . . etc . . . .

使用如下模式:

create table testSample
( 
    `_id` string, 
    something struct
    <
        $somefield:int,
        anotherfield:bigint, 
        yetanotherfield:int
    >
) 
row format serde 'org.openx.data.jsonserde.JsonSerDe' 
with serdeproperties
(
    "mapping.somefield" = "$somefield"
);

此架构构建正常,但是,上表中的某个字段(以 $ 开头)始终返回 null(所有其他值都存在且正确)。

我们尝试了很多语法组合,但都无济于事。

有谁知道在其名称中创建一个带有前导 $ 的嵌套字段的技巧?

【问题讨论】:

  • 我可以建议你几件事:1)在create table 命令中将$somefield:int 转换为'$somefield':int。 2) 尝试使用不同的 JsonSerDe,例如 github.com/electrum/hive-serde
  • 如果有任何帮助,请告诉我

标签: json struct hive


【解决方案1】:

你几乎猜对了。尝试像这样创建表。 您犯的错误是,在 serde 属性(mapping.somefield =“$somefield”)中进行映射时,您说“在查找名为 'somefield' 的配置单元列时,查找 json 字段 '$somefield',但是在 hive 中,您使用美元符号定义了列,如果不是完全非法,那肯定不是 hive 中的最佳实践。

create table testSample
(
`_id` string,
something struct
<
    somefield:int,
    anotherfield:bigint,
    yetanotherfield:int
  >
)
row format serde 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties
(
"mapping.somefield" = "$somefield"
);

我用一些测试数据对其进行了测试:

{ "_id" : "123", "something": { "$somefield": 12, "anotherfield":13,"yetanotherfield":100}}
hive> select something.somefield from testSample;
OK
12

【讨论】:

  • 对不起,这是帖子中的错字($somefield:int),但实际上声明代码很好。所以对于像{ "_fld1": { "$fld1": "12345"},"fld2": "ABCD" } 这样的数据,表的创建是:CREATE TABLE Temp(_fld1 struct, fld2 string) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ("mapping.dfld1" = "$fld1"),但是当我选择表字段 dfld1 时,它始终为空,我是否遗漏了什么。谢谢
  • 使用您提供的表定义和数据对我来说效果很好,但我必须将 _fld1 放在反引号 (`_fld1`) 周围: hive> select * from temp; OK {"dfld1":"12345"} ABCD 是您使用的实际定义还是只是简化它?您使用的是什么版本的 serde/hive/hadoop?
  • 这对我也很有效:hive> select `_fld1`.dfld1 from temp;好的 12345
  • 我对以 $ 开头的字段名称有疑问,它一直返回 null。我在 CDH 5.5.0 上使用 Hive 版本 1.1.0 和 Hadoop 2.6.0。我想我只是在最近下载时才使用最新的 hive json serde。非常感谢您的帮助和时间。
  • 好的,所以为了确保这是一个特定于版本的问题,你能得到这些文件吗:congiu.net/files.zip,它有我使用的 create.sql 和 data.txt。查看它们并运行 hive -f create.sql (它将删除“临时”表并重新创建它)并告诉我它是否适合您。此外,serde 的 jar 也应该有版本号,但我不知道它安装在您的系统中的什么位置。
【解决方案2】:

我也突然开始看到这个问题,但对于普通的列名也是如此(没有特殊字符,如 $)

我正在从另一个内部表 (Table2) 填充一个外部表 (Temp),并希望以 JSON 格式输出 Temp 表。我希望输出 JSON 文件中的列名采用驼峰式,因此我还使用 Temp 表中的 Serdepoperties 来指定正确的名称。但是,我看到当我从 Temp 表中选择 * 时,它会为映射中使用其名称的列提供 NULL 值。

我正在运行 Hive 0.13。以下是命令:

创建表命令:

CREATE EXTERNAL TABLE Temp (
    data STRUCT<
        customerId:BIGINT, region:STRING, marketplaceId:INT, asin:ARRAY<STRING>>
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
WITH SERDEPROPERTIES ( 
    'mapping.customerid' = 'customerId',
    'mapping.marketplaceid' = 'marketplaceId'
) 
LOCATION '/output'; 

INSERT INTO TABLE Temp
    SELECT 
        named_struct ('customerId',customerId, 'region', region, 'marketplaceId', marketplaceId, 'asin', asin) 
    FROM Table2;

从温度中选择 *:

{"customerid":null,"region":"EU","marketplaceid":null,"asin":["B000FC1PZC"]}
{"customerid":null,"region":"EU","marketplaceid":null,"asin":["B000FC1C9G"]}

查看“customerid”和“marketplaceid”如何为空。生成的 JSON 文件为:

{"data":{"region":"EU","asin":["B000FC1PZC"]}}
{"data":{"region":"EU","asin":["B000FC1C9G"]}}

现在,如果我删除 with serdeproperties,表格开始获取所有值:

{"customerid":1,"region":"EU","marketplaceid":4,"asin":["B000FC1PZC"]}
{"customerid":2,"region":"EU","marketplaceid":4,"asin":["B000FC1C9G"]}

然后这样生成的JSON文件是:

{"data":{"region":"EU","marketplaceid":4,"asin":["B000FC1PZC"],"customerid":1}}
{"data":{"region":"EU","marketplaceid":4,"asin":["B000FC1C9G"],"customerid":2}}

【讨论】:

    猜你喜欢
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多