如何从物化视图中的 PARSE_JSON 中提取特定的键、值是 redshift

问题描述 投票:0回答:1

假设我期望以下 JSON:

{
  "key": "value"
}

我想创建一个物化视图,将

key
显示为一列。数据来自Kinesis Streaming Data,因此它必须支持增量刷新,因为它每分钟可能包含数百万条新记录。我尝试了几种方法,其中之一:

CREATE MATERIALIZED VIEW kd.streams
AUTO REFRESH NO
AS
SELECT approximate_arrival_timestamp   AS apx_arv_at,
       JSON_PARSE(kinesis_data).key    AS key_value
FROM kd_stream."kinesis-stream"
WHERE CAN_JSON_PARSE(kinesis_data);

结果是:

ERROR:  syntax error at or near "."
LINE 5:        JSON_PARSE(kinesis_data).key                      AS...

我尝试了

JSON_EXTRACT_PATH_TEXT
、投射到
JSON
以及其他一些方法。

如果我只是将列创建为 json (

JSON_PARSE(kinesis_data)
),它就可以工作,但这意味着我需要在其上构建另一个 MV。仅供参考
kinesis_data
binary varying
kinesis-stream
是运动流(不是表)。

json amazon-redshift amazon-kinesis
1个回答
0
投票

根据您正在尝试的内容,我假设 kinesis_data 是字符串/文本。您看到的错误是因为查询解析器在运行时不知道“key”。您会看到这个超级值直到运行时才创建。所以当它看到“.”时它不知道该怎么办。

如果 kinesis_data 是 super 类型,则使用“.”当解析器知道这是 super 的(潜在)部分时,符号将起作用。如果您认为 Redshift 在这方面应该更聪明,我怀疑您需要提交案例。

现在获得您想要的内容已经很简单了,但首先我需要了解“转换为 JSON”的含义,因为 JSON 不是 Redshift 数据类型。我猜你想要一个只有字符串的 super,但这还不清楚。

我将重点关注 MV 定义中的选择查询,因为这是问题所在。

修复 #1 - 添加 with 子句。

如果我们从以下定义的测试表开始:

create table test as select '{
  "key": "value"
}' as col;

我们可以通过以下方式提取值:

with super as (
SELECT JSON_PARSE(col)    AS key_value
FROM test
WHERE CAN_JSON_PARSE(col))
select key_value, key_value.key
from super;

修复 #2 - 使用 JSON_EXTRACT_PATH_TEXT

使用与 #1 相同的测试表,我们可以:

SELECT col, json_parse('"'||JSON_EXTRACT_PATH_TEXT(col,'key')||'"')    AS key_value
FROM test
WHERE CAN_JSON_PARSE(col);

如果您想要一个字符串而不是 super,则不需要 json_parse 和这里的所有引用。

最后,作为健全性检查,解析器如何处理“.”。当表数据为超级时的表示法:

create table test2 as select json_parse('{
  "key": "value"
}') as col;

select col.key 
from test2;

我希望这可以帮助您获得所需的东西。

==============================更新==================== ========

根据评论,这里有一些修改后的代码。

创建测试表作为 varbyte 数据:

create table test as select '{
  "key": "value"
}'::varbyte as col;

用代码1制作物化视图:

create materialized view public.ttt 
auto refresh no
as 
with super as (
SELECT JSON_PARSE(col)    AS key_value
FROM test
WHERE CAN_JSON_PARSE(col))
select key_value, key_value.key
from super;

这可以工作,但由于从超类型(不可追踪)中提取“密钥”而无法增量更新,并且可能使用也增加了一些间接性的 cte。

从代码2制作物化视图:

create materialized view public.ttt 
auto refresh no
as 
SELECT col, json_parse('"'||JSON_EXTRACT_PATH_TEXT(col,'key')||'"')    AS key_value
FROM test
WHERE CAN_JSON_PARSE(col);

这没有增量更新限制。

© www.soinside.com 2019 - 2024. All rights reserved.