我正在尝试执行加载/复制操作,以便将数据从S3存储桶中的JSON文件直接导入Redshift。 COPY操作成功,在COPY之后,表具有正确的行/记录数,但每条记录都为NULL!
加载需要预期的时间,COPY命令返回OK,Redshift控制台报告成功且没有错误......但是如果我从表中执行简单查询,它只返回NULL值。
JSON非常简单+平坦,格式正确(根据我在此处找到的示例:http://docs.aws.amazon.com/redshift/latest/dg/r_COPY_command_examples.html)
基本上,每行一行,格式如下:
{ "col1": "val1", "col2": "val2", ... }
{ "col1": "val1", "col2": "val2", ... }
{ "col1": "val1", "col2": "val2", ... }
我尝试过根据JSON对象中的值和数据类型重写架构,以及从未压缩文件复制。我想也许JSON在加载时没有被正确解析,但如果无法解析对象,它可能会引发错误。
我的COPY命令如下所示:
copy events from 's3://mybucket/json/prefix'
with credentials 'aws_access_key_id=xxx;aws_secret_access_key=xxx'
json 'auto' gzip;
任何指导将不胜感激!感谢。
答案 0 :(得分:18)
所以我发现了原因 - 这在我原帖中提供的描述中并不明显。
在Redshift中创建表时,列名称将转换为小写。 执行COPY操作时,列名称区分大小写。
我一直在尝试加载的输入数据是使用camelCase作为列名,因此当我执行COPY时,列与定义的模式(现在使用所有小写列名称)不匹配
但该操作不会引发错误。它只会在所有不匹配的列中留下NULL(在本例中为所有列)
希望这有助于避免同样的混乱!
答案 1 :(得分:1)
这可能是因为 redshift 表的列名是小写的,而 JSON 文件中的列名是大写的(或驼峰式的)。作为一种解决方法,我们可以使用 'auto ignorecase' 而不是 'auto' 选项,并且 redshift 尝试匹配相应的列。 https://docs.aws.amazon.com/en_us/redshift/latest/dg/copy-parameters-data-format.html#copy-json
复制参数部分提到了信息。
答案 2 :(得分:0)
对于JSON数据对象不直接与列名对应的情况,您可以使用JSONPaths文件将JSON元素映射到TimZ所提及的列,并描述here
答案 3 :(得分:0)
COPY将JSON源数据中的数据元素映射到其中的列 通过匹配源中的对象键或名称来目标表 名称/值对与目标表中列的名称。的 匹配区分大小写。 Amazon Redshift表中的列名称为 总是小写,因此当您使用“自动”选项时,匹配JSON 字段名称也必须小写。如果不是JSON字段名称键 全部小写,您可以使用JSONPaths文件显式映射列 名称到JSON字段名称键。
解决方案是使用jsonpath
示例json:
{
"Name": "Major",
"Age": 19,
"Add": {
"street":{
"st":"5 maint st",
"ci":"Dub"
},
"city":"Dublin"
},
"Category_Name": ["MLB","GBM"]
}
示例表:
(
name varchar,
age int,
address varchar,
catname varchar
);
示例jsonpath:
{
"jsonpaths": [
"$['Name']",
"$['Age']",
"$['Add']",
"$['Category_Name']"
]
}
示例复制代码:
copy customer --redshift code
from 's3://mybucket/customer.json'
iam_role 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
json from 's3://mybucket/jpath.json' ; -- Jsonpath file to map fields
示例取自here