Redshift COPY с использованием JSONPath для отсутствующего массива / полей - PullRequest
0 голосов
/ 13 декабря 2018

Я использую команду COPY для загрузки набора данных JSON из S3 в таблицу Redshift.Данные загружаются частично, но игнорируются записи, в которых отсутствуют данные (ключ-значение / массив), т.е. из приведенного ниже примера будет загружена только первая запись.

Запрос:

COPY адрес из 's3: //mybucket/address.json'
учетных данных' aws_access_key_id = XXXXXXX; aws_secret_access_key = XXXXXXX 'maxerror as 250
json' s3: /mybucket/address_jsonpath.json '*;1009 *

Мой вопрос заключается в том, как загрузить все записи из address.json, даже если в некоторых записях отсутствует ключ / данные, аналогично приведенному ниже образцу набора данных.

Образец JSON

{
  "name": "Sam P",
  "addresses": [
    {
      "zip": "12345",
      "city": "Silver Spring",
      "street_address": "2960 Silver Ave",
      "state": "MD"
    },
    {
      "zip": "99999",
      "city": "Curry",
      "street_address": "2960 Silver Ave",
      "state": "PA"
    }
  ]
}
{
  "name": "Sam Q",
  "addresses": [ ]
}
{
  "name": "Sam R"
}

Есть ли альтернатива FILLRECORD для набора данных JSON?

Я ищу реализацию или обходной путь, который может загрузить все вышеперечисленное 3записи в таблице Redshift.

1 Ответ

0 голосов
/ 14 декабря 2018

Нет эквивалента FILLRECORD для COPY от JSON. Это явно не поддерживается в документации.

Но у вас есть более фундаментальная проблема - первая запись содержит массив, кратный addresses.Redshift COPY из JSON не позволяет вам создавать несколько строк из вложенных массивов.

Самый простой способ решить эту проблему - определить файлы для загрузки как внешнюю таблицу и использовать наш Синтаксис вложенных данных , чтобы развернуть встроенный массив в полные строки.Затем используйте INSERT INTO для загрузки данных в итоговую таблицу.

DROP TABLE IF EXISTS spectrum.partial_json;
CREATE EXTERNAL TABLE spectrum.partial_json (
  name       VARCHAR(100),
  addresses  ARRAY<STRUCT<zip:INTEGER
                         ,city:VARCHAR(100)
                         ,street_address:VARCHAR(255)
                         ,state:VARCHAR(2)>>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://my-test-files/partial_json/'
;

INSERT INTO final_table 
SELECT ext.name
     , address.zip
     , address.city
     , address.street_address
     , address.state
FROM spectrum.partial_json ext
LEFT JOIN ext.addresses address ON true
;
--  name  |  zip  |     city      | street_address  | state
-- -------+-------+---------------+-----------------+-------
--  Sam P | 12345 | Silver Spring | 2960 Silver Ave | MD
--  Sam P | 99999 | Curry         | 2960 Silver Ave | PA
--  Sam Q |       |               |                 |
--  Sam R |       |               |                 |

Примечание: я немного подправил ваш пример JSON, чтобы сделать это проще.Например, у вас были неключевые объекты в качестве значений для name, которые я превратил в простые строковые значения.

...