【问题标题】:Presto/Athena - query to discover JSON attribute frequencies?Presto/Athena - 查询以发现 JSON 属性频率?
【发布时间】:2017-09-04 22:06:34
【问题描述】:

我定义了一个 Hive 表,其中单列包含 JSON 文本:

CREATE EXTERNAL TABLE IF NOT EXISTS my.rawdata (
  json string
)
PARTITIONED BY (dt string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
   'separatorChar' = '\n',
   'quoteChar' = '\0',
   'escapeChar' = '\r'
)
STORED AS TEXTFILE
LOCATION 's3://mydata/';

是否有 Presto/Athena 查询可以列出 JSON 中出现的所有字段名称及其频率(即属性在表中出现的总次数)?

【问题讨论】:

  • 附言。表定义一团糟。 OpenCSVSerde?引用字符?转义字符?
  • OpenCSVSerde 是 Athena 提供的选项之一。我现在正在使用org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,但这并没有什么区别。对于 quoteChar 和 escapeChar 我只需要文件中不存在的字符。

标签: json presto amazon-athena


【解决方案1】:

使用 JSON 函数解析 JSON 并将其转换为地图。然后提取密钥和unnest。最后,使用普通的 SQL 聚合:

SELECT key, count(*)
FROM (
  SELECT map_keys(cast(json_parse(json) AS map(varchar, json))) AS keys
  FROM rawdata
)
CROSS JOIN UNNEST (keys) AS t (key)
GROUP BY key

【讨论】:

  • 限于单级文档
  • 附言。不需要子查询,可以在keys别名的表达式上执行UNNEST
  • 这很好用。使用正则表达式的另一个答案不能正确处理转义引号。
【解决方案2】:
  • 支持多级文档
  • 忽略嵌套元素的键

select    key
         ,count(*)
from      t cross join 
          unnest (regexp_extract_all(json,'"([^"]+)"\s*:\s*("[^"]+"|[^,{}]+)',1)) u (key)
group by  key
;

【讨论】:

  • 运行良好,功能强大。在 json 上使用正则表达式感觉不对,尽管在这个问题中 json 字段实际上是一个 varchar 类型(hive 字符串),所以正则表达式可能适合该数据类型。正如您所指出的,表定义是一团糟。
  • 另外,这个答案交换了另一个答案中单级的限制,如果同一键出现在json中的多个级别,结果将不正确。
猜你喜欢
  • 2019-04-07
  • 2020-02-11
  • 2020-08-15
  • 2020-01-13
  • 2020-01-27
  • 1970-01-01
  • 2020-06-10
  • 2017-06-17
  • 1970-01-01
相关资源
最近更新 更多