首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BigQuery:存储半结构化JSON数据

BigQuery:存储半结构化JSON数据
EN

Stack Overflow用户
提问于 2019-03-03 10:49:19
回答 1查看 1.4K关注 0票数 3

我有可以拥有不同json键的数据,我希望将所有这些数据存储在bigquery中,然后在以后探索可用的字段。

我的结构会是这样的:

代码语言:javascript
复制
[
{id: 1111, data: {a:27, b:62, c: 'string'} },
{id: 2222, data: {a:27, c: 'string'} },
{id: 3333, data: {a:27} },
{id: 4444, data: {a:27, b:62, c:'string'} },
]

我想使用STRUCT类型,但似乎所有字段都需要声明?

然后,我希望能够查询和查看每个键出现的频率,基本上可以像在自己的列中一样使用a键对所有记录运行查询。

附带注意:这些数据来自URL查询字符串,也许有人认为最好按下完整的url并使用函数来运行分析?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-04 05:25:27

有两种存储半结构化数据的主要方法,如您在示例中所使用的:

选项1:存储JSON字符串

您可以将data字段存储为JSON,然后使用JSON_EXTRACT函数提取它可以找到的值,它将返回任何它找不到的值的NULL

既然您提到需要对字段进行数学分析,那么让我们为ab的值做一个简单的b

代码语言:javascript
复制
# Creating an example table using the WITH statement, this would not be needed
# for a real table.
WITH records AS (
  SELECT 1111 AS id, "{\"a\":27, \"b\":62, \"c\": \"string\"}" as data
  UNION ALL
  SELECT 2222 AS id, "{\"a\":27, \"c\": \"string\"}" as data
  UNION ALL
  SELECT 3333 AS id, "{\"a\":27}" as data
  UNION ALL
  SELECT 4444 AS id, "{\"a\":27, \"b\":62, \"c\": \"string\"}" as data
)

# Example Query
SELECT SUM(aValue) AS aSum, SUM(bValue) AS bSum FROM (
  SELECT id, 
    CAST(JSON_EXTRACT(data, "$.a") AS INT64) AS aValue, # Extract & cast as an INT
    CAST(JSON_EXTRACT(data, "$.b") AS INT64) AS bValue  # Extract & cast as an INT
  FROM records
)

# results
# Row | aSum | bSum
# 1   | 108  | 124

这种方法有一些优点和缺点:

Pros

  • 语法相当直白。
  • 较少出错

Cons

  • 存储成本会稍微高一些,因为您必须存储所有字符才能序列化为JSON。
  • 查询将比使用纯原生SQL运行得慢。

选项2:重复字段

BigQuery有对重复字段的支持,允许您使用您的结构并在本机中用SQL表示它。

使用同样的例子,我们将如何做到这一点:

代码语言:javascript
复制
## Using a with to create a sample table
WITH records AS (SELECT * FROM UNNEST(ARRAY<STRUCT<id INT64, data ARRAY<STRUCT<key STRING, value STRING>>>>[
  (1111, [("a","27"),("b","62"),("c","string")]),
  (2222, [("a","27"),("c","string")]),
  (3333, [("a","27")]),
  (4444, [("a","27"),("b","62"),("c","string")])
])),
## Using another WITH table to take records and unnest them to be joined later
recordsUnnested AS (
  SELECT id, key, value
  FROM records, UNNEST(records.data) AS keyVals
)

SELECT SUM(aValue) AS aSum, SUM(bValue) AS bSum
FROM (
  SELECT R.id, CAST(RA.value AS INT64) AS aValue, CAST(RB.value AS INT64) AS bValue
  FROM records R
    LEFT JOIN recordsUnnested RA ON R.id = RA.id AND RA.key = "a"
    LEFT JOIN recordsUnnested RB ON R.id = RB.id AND RB.key = "b"
)

# results
# Row | aSum | bSum
# 1   | 108  | 124

正如您所看到的,要执行类似的操作,它仍然相当复杂。您还必须在必要时将字符串之类的项存储到其他值中,因为不能在重复字段中混合类型。

Pros

  • 商店大小将小于JSON
  • 查询通常会执行得更快。

Cons

  • 语法更复杂,不像前面那么简单。

希望这能帮上忙祝你好运。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54968020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档