Redshift Spectrum:查询匿名JSON数组结构

时间:2019-05-02 02:14:13

标签: amazon-web-services amazon-redshift aws-glue amazon-redshift-spectrum

我在S3中具有一个JSON结构数组,该数组已由Glue成功地进行了爬网和分类。

[{"key":"value"}, {"key":"value"}]

我正在使用自定义分类器:

$[*] 

但是,当尝试从Spectrum查询时,它返回:

  

仅当且仅当顶级Ion / JSON结构必须为匿名数组   设置serde属性“ strip.outer.array”。文件中出现不匹配...

我在Glue目录表中手动设置了serde属性,但没有任何改变。

是否不可能通过Spectrum查询匿名数组?

4 个答案:

答案 0 :(得分:1)

像这样在JSON文件中命名数组:

"values":[{"key":"value"},...}

并更新分类器:

$.values[*]

解决了该问题...有兴趣知道是否有一种查询匿名数组的方法。像这样存储数据似乎很常见。

更新: 最终,该解决方案不起作用,因为Spectrum永远不会返回任何结果。没有错误,只有结果,到目前为止,除了每行使用单个记录外,还没有解决方案:

{"key":"value"}
{"key":"value"}
etc.

这似乎是特定于Spectrum的问题,因为Athena仍然可以使用。

有兴趣知道其他人是否能够使它正常工作...

答案 1 :(得分:1)

您可以使用json_extract_path_text提取元素或json_extract_array_element_text('json字符串',pos [,null_if_invalid])。

例如: 对于第二个索引元素 选择json_extract_array_element_text('[111,112,113]',2);

输出:113

答案 2 :(得分:0)

如果表的结构如下:

this.setState(currentState=>({...currentState, loginSuccess:status))

您可以使用以下查询访问数组元素:

CREATE EXTERNAL TABLE spectrum.testjson(struct<id:varchar(25), 
columnName<array<struct<key:varchar(20),value:varchar(20)>>>);

有关更多信息,请参阅AWS文档:

{{3}}

答案 3 :(得分:0)

我已成功完成此操作,但没有数据分类器。我的JSON文件如下:

[
    {
        "col1": "data_from_col1",
        "col2": "data_from_col2",
        "col3": [
            {
                "col4": "data_from_col4",
                ...
            {
        ]
    },
    {
        "col1": "data_from_col1",
        "col2": "data_from_col2",
        "col3": [
            {
                "col4": "data_from_col4",
                ...
            {
        ]
    },
    ...
]

我从搜寻器开始获得基本的表定义。重要提示:无法将“输出”下的搜寻器的配置选项设置为“更新表定义...”,否则稍后重新运行搜寻器将覆盖下面描述的手动更改。我只使用“添加新列”。

我必须添加'strip.outer.array'属性,并手动在我的匿名数组中添加最上面的列。最初的搜寻器运行时的原始架构为:

anon_array array<struct<col1:string,col2:string,col3:array<struct<col4...>>>
partition_0 string

我手动将架构更新为:

col1:string
col2:string
col3:array<struct<col4...>>
partition_0 string

(还要添加Serde参数param.outer.array。)

然后我必须重新运行我的搜寻器,最后我可以在Spectrum中进行查询,例如:

select o.partition_0, o.col1, o.col2, t.col4
from db.tablename o
LEFT JOIN o.col3 t on true;