BigQuery: хранение полуструктурированных данных JSON - PullRequest
0 голосов
/ 03 марта 2019

У меня есть данные, которые могут иметь различные json ключи, я хочу сохранить все эти данные в bigquery, а затем изучить доступные поля.

Моя структура будет выглядеть так:

[
{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 и использовать функции для запуска анализа?

1 Ответ

0 голосов
/ 04 марта 2019

Существует два основных способа хранения полуструктурированных данных, как в вашем примере:

Опция # 1: Сохранить строку JSON

Вы можете сохранитьdata поле в виде строки JSON, а затем используйте функцию JSON_EXTRACT, чтобы извлечь значения, которые он может найти, и он вернет NULL для любого значения, которое он не может найти.

Так как вы упомянули о необходимости математического анализа полей, давайте сделаем простой SUM для значений a и b:

# 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

Есть некоторые плюсы и минусы в этомподход:

Плюсы

  • Синтаксис довольно прост
  • Меньше ошибок

Минусы

  • Расходы на хранилище будут несколько выше, поскольку вам нужно хранить все символы для сериализации в JSON.
  • Запросы будут выполняться медленнее, чем при использовании чистого собственного SQL.

Опция №2: повторяющиеся поля

BigQuery имеет поддержку для повторенияполя , позволяющие взять структуру и выразить ее в SQL.

Используя тот же пример, вот как мы это сделаем:

## 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

Как видите, выполнить аналогичное действие все еще довольно сложно.Вам также по-прежнему необходимо хранить такие элементы, как строки, и CAST их к другим значениям, когда это необходимо, поскольку вы не можете смешивать типы в повторяющемся поле.

Плюсы

  • Размер магазина будет меньше, чем JSON
  • Запросы обычно выполняются быстрее.

Минусы

  • Синтаксис большесложный, не такой прямой

Надеюсь, это поможет, удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...