Могу ли я преобразовать строковый массив JSON обратно в структуру BigQuery? - PullRequest
1 голос
/ 17 января 2020

Я пытаюсь взять поле STRING, содержащее вложенную структуру JSON, из таблицы с именем my_old_table, извлечь из нее вложенный массив с именем «alert», а затем вставить его в столбец новой таблицы с именем my_new_table. Новый столбец определен как:

ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>

Я использую это SQL:

INSERT INTO my_dataset.my_table(
   id, alerts)
SELECT id, JSON_EXTRACT(extra, "$.alerts") AS content_alerts
FROM my_dataset.my_old_table

Это дает мне:

Query column 2 has type STRING which cannot be inserted into column content_alerts, which has type ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>> at [4:1]

Я не не вижу способа синтаксического анализа извлеченной строки обратно в структуру .... Есть ли другой способ сделать это?

Редактировать:

Исходное значение json строка , которая выглядит следующим образом:

{
  "id": "bar123",
  "value": "Test",
  "title": "Test",
  "alerts": [
    {
      "id": "abc123",
      "title": "Foo",
      "created": "2020-01-17T23:18:59.769908Z"
    },
    {
      "id": "abc124",
      "title": "Accepting/Denying Claims",
      "created": "2020-01-17T23:18:59.769908Z"
    }
  ]
}

Я хочу извлечь $.alerts и каким-то образом вставить его в ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>.

Edit # 2

Для пояснения, это воспроизводит проблему:

CREATE TABLE insights.my_table
(
  id string,
  alerts ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>
);

CREATE TABLE insights.my_old_table
(
   id string,
   field STRING
);

INSERT INTO insights.my_old_table(id, field)
VALUES("1", "{\"id\": \"bar123\",\"value\": \"Test\",\"title\": \"Test\",\"alerts\":[{\"id\": \"abc123\",\"title\": \"Foo\",\"created\": \"2020-01-17T23:18:59.769908Z\"},{\"id\": \"abc124\",\"title\": \"Accepting/Denying Claims\",\"created\": \"2020-01-17T23:18:59.769908Z\"}]}");

На основании вышеописанной настройки я не знаю, как извлечь "оповещения" из STRING и вставьте его в поле STRUCT. Я думал, что мог бы добавить туда шаг JSON PARSE, но я не вижу никакой возможности BigQuery для этого. Иначе был бы способ манипулировать JSON СТРУКТУРОЙ, но я тоже этого не вижу. В результате это настолько близко, насколько я мог бы получить:

INSERT INTO insights.my_table(id, alerts)
SELECT id, JSON_EXTRACT(field, "$.alerts") AS alerts FROM insights.my_old_table

Я уверен, что здесь что-то упущено.

Ответы [ 2 ]

2 голосов
/ 17 января 2020

Ниже для BigQuery Standard SQL

#standardSQL
CREATE TEMP FUNCTION JsonToItems(input STRING)
RETURNS ARRAY<STRING>
LANGUAGE js AS """
  return JSON.parse(input).map(x=>JSON.stringify(x));
"""; 
)
SELECT 
  JSON_EXTRACT_SCALAR(extra, "$.id") AS id,
  ARRAY(
    SELECT AS STRUCT 
      JSON_EXTRACT_SCALAR(alert, "$.id") AS cuid,
      JSON_EXTRACT_SCALAR(alert, "$.title") AS title,
      TIMESTAMP(JSON_EXTRACT_SCALAR(alert, "$.created")) AS created
    FROM UNNEST(JsonToItems(JSON_EXTRACT(extra, "$.alerts"))) alert 
  ) AS alerts,
FROM `project.dataset.my_old_table`   

Вы можете протестировать, поиграть с выше, используя примеры данных из вашего вопроса, как в примере ниже

#standardSQL
CREATE TEMP FUNCTION JsonToItems(input STRING)
RETURNS ARRAY<STRING>
LANGUAGE js AS """
  return JSON.parse(input).map(x=>JSON.stringify(x));
"""; 
WITH `project.dataset.my_old_table` AS (
  SELECT '''
{
  "id": "bar123",
  "value": "Test",
  "title": "Test",
  "alerts": [
    {
      "id": "abc123",
      "title": "Foo",
      "created": "2020-01-17T23:18:59.769908Z"
    },
    {
      "id": "abc124",
      "title": "Accepting/Denying Claims",
      "created": "2020-01-17T23:18:59.769908Z"
    }
  ]
}
''' extra
)
SELECT 
  JSON_EXTRACT_SCALAR(extra, "$.id") AS id,
  ARRAY(
    SELECT AS STRUCT 
      JSON_EXTRACT_SCALAR(alert, "$.id") AS cuid,
      JSON_EXTRACT_SCALAR(alert, "$.title") AS title,
      TIMESTAMP(JSON_EXTRACT_SCALAR(alert, "$.created")) AS created
    FROM UNNEST(JsonToItems(JSON_EXTRACT(extra, "$.alerts"))) alert 
  ) AS alerts,
FROM `project.dataset.my_old_table`    

с результатом

enter image description here

Очевидно, что вы можете использовать это в своем INSERT INTO my_dataset.my_table утверждении

0 голосов
/ 17 января 2020

Вы можете проанализировать извлеченную строку обратно в структуру BigQuery следующим образом:

SELECT STRUCT(ARRAY<STRUCT<cuid STRING, title STRING, created TIMESTAMP>>
[('Rick', 'Scientist', '2020-01-17')]) FROM my_dataset.my_old_table;

Я только что попробовал это с вашими данными

Я вставил ваши данные в таблицу BigQuery:

INSERT INTO dataset.table
  VALUES('{"id": "bar123", "value": "Test", "title": "Test", "alerts":
 [{ "id": "abc123", "title": "Foo", "created": "2020-01-17T23:18:59.769908Z"},
 {"id": "abc124", "title": "Accepting/Denying Claims", "created": "2020-01-17T23:18:59.769908Z"}]}');

и запросил их, преобразовав обратно в структуру BigQuery:

SELECT STRUCT<cuid STRING, title STRING, created TIMESTAMP>("abc123",
 "Foo", "2020-01-17T23:18:59.769908Z"),("abc124", "Accepting/Denying 
 Claims", "2020-01-17T23:18:59.769908Z") FROM blabla.testingjson;

Вывод:

Row | f0_.cuid | f0_.title | f0_.created 
----------------------------------------
1   | abc123   | Foo       | 2020-01-17 23:18:59.769908 UTC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...