Какой формат JSON поддерживает STRIP_OUTER_ARRAY? - PullRequest
0 голосов
/ 21 октября 2019

У меня есть файл, состоящий из одного массива, содержащего несколько записей.

{
    "Client": [
        {
            "ClientNo": 1,
            "ClientName": "Alpha",
            "ClientBusiness": [
                {
                    "BusinessNo": 1,
                    "IndustryCode": "12345"
                },
                {
                    "BusinessNo": 2,
                    "IndustryCode": "23456"
                }
            ]
        },
        {
            "ClientNo": 2,
            "ClientName": "Bravo",
            "ClientBusiness": [
                {
                    "BusinessNo": 1,
                    "IndustryCode": "34567"
                },
                {
                    "BusinessNo": 2,
                    "IndustryCode": "45678"
                }
            ]
        }
    ]
}

Я загружаю его со следующим кодом:

create or replace stage stage.test
  url='azure://xxx/xxx'
  credentials=(azure_sas_token='xxx');

create table if not exists stage.client (json_data variant not null);

copy into stage.client_test
from @stage.test/client_test.json
file_format = (type = 'JSON' strip_outer_array = true);

Снежинка импортирует весь файл как одну строку.

Мне бы хотелось, чтобы команда COPY INTO удалила структуру внешнего массива и загрузила записи в отдельные строки таблицы.

Когда я загружаю большие файлы, я достигаю предела размера для варианта иполучите ошибку Error parsing JSON: document is too large, max size 16777216 bytes.

Ответы [ 2 ]

1 голос
/ 22 октября 2019

Если вы можете импортировать файл в Snowflake в одну строку, то вы можете использовать LATERAL FLATTEN в поле Clients для генерации одной строки на элемент в массиве.

Вот сообщение в блоге на LATERAL иFLATTEN (или вы можете посмотреть их в документах о снежинках): https://support.snowflake.net/s/article/How-To-Lateral-Join-Tutorial

Если формат файла, как указано, один объект с единственным свойством, который содержит массив с стоимостью 500 МБэлементы в нем, тогда, возможно, его импорт все равно будет работать - если это работает, то LATERAL FLATTEN - это именно то, что вам нужно. Но эта форма не особенно хороша для обработки данных. Возможно, вы захотите использовать какой-нибудь скрипт обработки текста, чтобы обработать данные, если это необходимо.

0 голосов
/ 21 октября 2019

РЕКОМЕНДАЦИЯ № 1:

Проблема с вашим JSON состоит в том, что у него нет внешнего массива. У него есть один внешний объект, содержащий свойство с внутренним массивом.

Если вы можете исправить JSON, это будет лучшим решением, и тогда STRIP_OUTER_ARRAY будет работать так, как вы ожидаете.

ВыМожно также попытаться изменить JSON (уродливый бизнес) после прочтения строки для строки с:

CREATE OR REPLACE TABLE X (CLIENT VARCHAR);
COPY INTO X FROM (SELECT $1 CLIENT FROM @My_Stage/Client.json);

Ответ пользователя на Рекомендацию № 1:

Спасибо. Итак, из того, что я понял, COPY with STRIP_OUTER_ARRAY может обрабатывать файл, начинающийся и заканчивающийся квадратными скобками, и анализировать файл, как если бы его там не было.

В реальных файлах нет разрывов строк, поэтому я могучитать файл построчно. Я посмотрю, может ли исходная система изменить экспорт.


РЕКОМЕНДАЦИЯ № 2:

Также, если вы хотите увидетьЧто делает анализатор JSON, вы можете поэкспериментировать с этим кодом. Я проанализировал JSON в команде копирования с использованием аналогичного кода. Работа с данными JSON в небольшом проекте может помочь вам настроить команду «Копировать» для правильной работы.

CREATE OR REPLACE TABLE SAMPLE_JSON
(ID INTEGER,
DATA VARIANT
);

INSERT INTO SAMPLE_JSON(ID,DATA)
SELECT
1,parse_json('{
  "Client": [
    {
      "ClientNo": 1,
      "ClientName": "Alpha",
      "ClientBusiness": [
        {
          "BusinessNo": 1,
          "IndustryCode": "12345"
        },
        {
          "BusinessNo": 2,
          "IndustryCode": "23456"
        }
      ]
    },
    {
      "ClientNo": 2,
      "ClientName": "Bravo",
      "ClientBusiness": [
        {
          "BusinessNo": 1,
          "IndustryCode": "34567"
        },
        {
          "BusinessNo": 2,
          "IndustryCode": "45678"
        }
      ]
    }
  ]
}');

SELECT 
 C.value:ClientNo AS ClientNo
,C.value:ClientName::STRING AS ClientName
,ClientBusiness.value:BusinessNo::Integer AS BusinessNo
,ClientBusiness.value:IndustryCode::Integer AS IndustryCode
from SAMPLE_JSON f
,table(flatten( f.DATA,'Client' )) C
,table(flatten(c.value:ClientBusiness,'')) ClientBusiness;

enter image description here

Ответ пользователя на Рекомендацию № 2:

Спасибо за пример parse_json!

Проблема в том, что реальные файлы иногда имеют размер 500 МБ, поэтому функция parse_json задыхается.

Выполнение рекомендации № 2:

JSON должен быть в формате NDJSON http://ndjson.org/. В противном случае JSON будет невозможно проанализировать из-за возможности больших файлов.


Надеюсь, что вышеизложенное помогает другим сталкиваться с подобными вопросами!

...