Использование коннекторов PXF object store для чтения и записи JSON-данных между Greengage DB и S3
JSON — текстовый формат обмена данными. Данные JSON представляют собой коллекцию объектов, каждый из которых является набором неупорядоченных пар имя/значение. Значением может быть строка, число, логическое значение, null, а также вложенный объект или массив.
Данные JSON обычно хранятся в файле с суффиксом .json или .jsonl (JSON Lines). Подробную информацию о синтаксисе JSON можно найти в статье Introducing JSON. Подробную информацию о синтаксисе JSON Lines можно найти в статье JSON Lines.
С помощью коннекторов PXF object store можно читать и записывать данные, хранящиеся в объектных хранилищах Azure Blob Storage, Azure Data Lake, Google Cloud Storage, Amazon S3, MinIO и других, совместимых с S3.
В этой статье описывается настройка и использование коннектора PXF object store для чтения и записи данных JSON в объектном хранилище с использованием внешних таблиц, а также приводятся практические примеры.
Подробная информация о работе с типом данных JSON напрямую в Greengage DB приведена в статье Работа с данными JSON.
Режимы доступа к данным JSON
PXF поддерживает два режима доступа к данным JSON.
Режим одного объекта на строку (по умолчанию) предполагает одну полную JSON-запись на строку, где каждая строка представляет кортеж базы данных. В этом режиме файлы JSON, читаемые PXF, могут иметь любой суффикс или не иметь его вообще. При записи данных PXF создает файл с суффиксом .jsonl.
Файл данных JSON с одним объектом на строку выглядит подобным образом:
{"id":1,"color":"red"}
{"id":2,"color":"yellow"}
{"id":3,"color":"green"}
Режим одного объекта на файл работает с одним объектом JSON на файл, а записи JSON могут охватывать несколько строк.
Файл JSON также может содержать один именованный корневой JSON-объект, значением которого является массив объектов JSON.
При чтении данных массив может содержать объекты произвольной сложности и вложенности, а PXF формирует кортежи базы данных из объектов, у которых есть свойство с именем, совпадающим со значением опции IDENTIFIER (описана ниже).
При записи данных каждый JSON-объект в массиве представляет собой кортеж базы данных.
Файлы JSON этого типа имеют суффикс .json.
В файлах данных JSON не должно быть пустых строк.
Образец файла данных JSON для одного объекта на файл выглядит подобным образом.
Корневой объект records является массивом из трех объектов (кортежей):
{
"records": [
{
"id": 1,
"color": "red"
},
{
"id": 2,
"color": "yellow"
},
{
"id": 3,
"color": "green"
}
]
}
При записи данных PXF по умолчанию создает файл с суффиксом .jsonl.
Если указано свойство ROOT (описано ниже), создается файл с суффиксом .json.
Сопоставление типов данных
Чтобы представить данные JSON в Greengage DB, сопоставьте значения данных, использующие примитивный тип данных, столбцам Greengage DB того же типа. JSON поддерживает сложные типы данных, включая проекции и массивы.
Сопоставление при чтении
При чтении JSON-данных с помощью PXF используется следующее сопоставление типов данных. Вы можете использовать N-уровневую проекцию для сопоставления элементов вложенных объектов и массивов с примитивными типами данных.
| Тип данных JSON | Тип данных PXF / Greengage |
|---|---|
boolean |
BOOLEAN |
number |
Один из следующих типов: |
string |
TEXT |
|
BYTEA |
|
Один из следующих типов: |
Одномерный массив типа |
BOOLEAN[] |
Одномерный массив типа |
Один из следующих типов: |
Одномерный массив типа |
BYTEA[] |
Одномерный массив типа |
|
Одномерный массив типа |
TEXT[] |
Массив других типов |
TEXT[] |
Object |
Используйте точечную нотацию ( |
Сопоставление при записи
PXF поддерживает запись примитивных типов и одномерных массивов примитивных типов. Другие сложные типы записываются в JSON как строки. PXF использует следующее сопоставление типов данных при записи данных JSON.
| Тип данных PXF / Greengage | Тип данных JSON |
|---|---|
|
number |
BOOLEAN |
boolean |
|
string |
BYTEA |
|
|
string |
BOOLEAN[] |
boolean[] |
|
number[] |
BYTEA[] |
|
|
string[] |
Использование проекции столбцов
В данном примере файла данных JSON объект user содержит поля id и location:
{
"created_at": "MonSep3004:04:53+00002013",
"id_str": "384529256681725952",
"user": {
"id": 31424214,
"location": "COLUMBUS"
},
"coordinates": {
"type": "Point",
"values": [
13,
99
]
}
}
Чтобы использовать вложенные поля объекта user в качестве столбцов внешней таблицы Greengage DB, используйте точечную проекцию (.):
user.id
user.location
Объект coordinates состоит из текстового поля type и целочисленного массива values.
Чтобы поместить все значения массива values в один столбец, укажите для соответствующего столбца внешней таблицы Greengage DB тип INT[]:
"coordinates.values" INT[]
PXF также поддерживает доступ к конкретным элементам JSON-массива с помощью скобочного синтаксиса [n] в определении таблицы.
Обратите внимание, что при использовании этого метода для идентификации конкретных элементов массива PXF предоставляет Greengage DB только эти значения, а не весь массив:
"coordinates.values[0]" INT
При записи данных JSON PXF поддерживает только скалярные значения или одномерные массивы типов данных Greengage DB и не поддерживает проекцию столбцов.
Создание внешней таблицы с использованием протокола PXF
Чтобы создать внешнюю таблицу Greengage DB для чтения и записи данных JSON в объектном хранилище, используется следующий синтаксис:
CREATE [READABLE | WRITABLE] EXTERNAL TABLE <table_name>
( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path_to_data>?PROFILE=<objstore>:json[&<custom_option>=<value>[...]]')
FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'|'pxfwritable_export')
[DISTRIBUTED BY (<column_name> [, ... ] ) | DISTRIBUTED RANDOMLY];
| Ключевое слово | Значение |
|---|---|
<table_name> |
Имя создаваемой таблицы |
<column_name> |
Имя создаваемого столбца |
<data_type> |
Тип данных создаваемого столбца |
LIKE <other_table> |
Указывает таблицу, из которой внешняя таблица копирует все имена столбцов, типы данных и политику распределения |
<path_to_data> |
Путь к каталогу или файлу в объектном хранилище.
Если в конфигурации сервера |
PROFILE=<objstore>:json |
Профиль указывается в виде пары Поддерживаются следующие префиксы
|
FORMAT 'CUSTOM' |
Для чтения и записи данных JSON в объектном хранилище используется кастомный формат с использованием встроенных кастомных функций форматирования для операций чтения ( |
<custom_option> |
Одна из опций, описанных ниже, указываемая в строке |
SERVER=<server_name> |
Имя конфигурации сервера, который используется для доступа к данным.
Если опция опущена, используется конфигурация сервера с именем |
IDENTIFIER=<value> |
Указывается только при обращении к данным JSON с многострочными полями.
Значение Если во вложенном объекте присутствует поле с тем же именем, что указано в качестве |
SPLIT_BY_FILE=<boolean> |
Определяет, как разделять файлы, указанные в |
IGNORE_MISSING_PATH=<boolean> |
Действие, которое необходимо выполнить, если |
ROOT=<value> |
При записи данных в один объект указывает имя атрибута корневого уровня |
COMPRESSION_CODEC |
Кодек сжатия, используемый при записи данных: |
При обращении к объектному хранилищу S3 вы можете предоставить учетные данные S3, указав опции accesskey и secretkey в выражении LOCATION команды CREATE EXTERNAL TABLE.
Примеры
Эти примеры демонстрируют настройку и использование коннектора PXF object store для чтения и записи данных JSON в объектном хранилище с помощью внешних таблиц.
Конфигурирование коннектора PXF S3
Для того чтобы подключиться к объектному хранилищу с помощью PXF, необходимо создать соответствующую конфигурацию сервера, а затем синхронизировать конфигурацию между хостами кластера Greengage DB:
-
На мастер-хосте Greengage DB войдите под пользователем
gpadmin. -
Перейдите в каталог $PXF_BASE/servers и создайте каталог конфигурации сервера S3 с именем s3. Скопируйте необходимый для используемого объектного хранилища файл конфигурации сервера из $PXF_HOME/templates в $PXF_BASE/servers/s3. В примере используется файл конфигурации на основе шаблона minio-site.xml.
$ mkdir $PXF_BASE/servers/s3 $ cd $PXF_BASE/servers/s3 $ cp $PXF_HOME/templates/minio-site.xml .В файле конфигурации укажите необходимые данные для подключения к объектному хранилищу:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property> <name>fs.s3a.endpoint</name> <value>storage.example.com</value> </property> <property> <name>fs.s3a.access.key</name> <value>${ACCESS_KEY}</value> </property> <property> <name>fs.s3a.secret.key</name> <value>${SECRET_KEY}</value> </property> <property> <name>fs.s3a.fast.upload</name> <value>true</value> </property> <property> <name>fs.s3a.path.style.access</name> <value>true</value> </property> </configuration>ПРИМЕЧАНИЕОбратите внимание, что учетные данные для подключения к объектному хранилищу указываются в виде переменных окружения
ACCESS_KEYиSECRET_KEY.Установить значения этих переменных можно следующим образом:
$ export ACCESS_KEY=<access_key> $ export SECRET_KEY=<secret_key>Учетные данные в файле конфигурации можно указать и в виде обычного текста, но в целях безопасности рекомендуется использовать переменные окружения.
-
Синхронизируйте конфигурацию между хостами кластера Greengage DB:
$ pxf cluster sync
Чтение JSON-файла с однострочными полями
-
В бакете customers на хосте S3 создайте файл с именем customers.jsonl и следующим содержимым:
{"customer": {"id": 1,"name": "John Doe"},"ordered_items":["laptop", "monitor"]} {"customer": {"id": 2,"name": "Jane Smith"},"ordered_items":["keyboard", "mouse", "pad"]} {"customer": {"id": 3,"name": "Bob Brown"},"ordered_items":["headphones"]} {"customer": {"id": 4,"name": "Alice Green"},"ordered_items":["webcam", "microphone"]} -
На мастер-хосте Greengage DB создайте внешнюю таблицу, ссылающуюся на файл customers.jsonl. При определении столбцов используйте точечную нотацию (
.) для доступа к вложенным полям объектаcustomer. Сопоставьте текстовый массивordered_itemsс текстовым столбцом Greengage DB (TEXT). В выраженииLOCATIONукажите PXF-профильs3:jsonи конфигурацию сервера. В выраженииFORMATукажитеpxfwritable_import— встроенную кастомную функцию форматирования для операций чтения:CREATE EXTERNAL TABLE customers_r_singleline_1 ( "customer.id" INT, "customer.name" TEXT, "ordered_items" TEXT ) LOCATION('pxf://customers/customers.jsonl?PROFILE=s3:json&SERVER=s3') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'); -
Выполните запрос к созданной внешней таблице:
SELECT * FROM customers_r_singleline_1;Вывод должен выглядеть следующим образом:
customer.id | customer.name | ordered_items -------------+---------------+---------------------------- 1 | John Doe | ["laptop","monitor"] 2 | Jane Smith | ["keyboard","mouse","pad"] 3 | Bob Brown | ["headphones"] 4 | Alice Green | ["webcam","microphone"] (4 rows)JSON-массив
ordered_itemsизвлекается в единый столбец текстового типа. Чтобы преобразовать его во встроенный тип массива Greengage DB, можно выполнить следующий запрос, использующий функцию json_array_elements_text():SELECT "customer.id", "customer.name", ARRAY(SELECT json_array_elements_text(ordered_items::json))::text[] AS items FROM customers_r_singleline_1;Вывод должен выглядеть следующим образом:
customer.id | customer.name | items -------------+---------------+---------------------- 1 | John Doe | {laptop,monitor} 2 | Jane Smith | {keyboard,mouse,pad} 3 | Bob Brown | {headphones} 4 | Alice Green | {webcam,microphone} (4 rows) -
На мастер-хосте Greengage DB создайте еще одну внешнюю таблицу, ссылающуюся на файл customers.jsonl. Сопоставьте текстовый массив
ordered_itemsс текстовым массивом Greengage DB (TEXT[]):CREATE EXTERNAL TABLE customers_r_singleline_2 ( "customer.id" INT, "customer.name" TEXT, "ordered_items" TEXT[] ) LOCATION('pxf://customers/customers.jsonl?PROFILE=s3:json&SERVER=s3') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'); -
Выполните запрос к созданной внешней таблице, используя номер индекса массива в квадратных скобках, чтобы извлечь первый элемент массива
ordered_items:SELECT "customer.id", "customer.name", "ordered_items"[1] FROM customers_r_singleline_2;Вывод должен выглядеть следующим образом:
customer.id | customer.name | ordered_items -------------+---------------+--------------- 1 | John Doe | laptop 2 | Jane Smith | keyboard 3 | Bob Brown | headphones 4 | Alice Green | webcam (4 rows) -
На мастер-хосте Greengage DB создайте еще одну внешнюю таблицу, ссылающуюся на файл customers.jsonl. Используйте номер индекса массива в квадратных скобках, чтобы извлечь второй элемент массива
ordered_items, и сопоставьте его с текстовым столбцом Greengage DB:CREATE EXTERNAL TABLE customers_r_singleline_3 ( "customer.id" INT, "customer.name" TEXT, "ordered_items[1]" TEXT ) LOCATION('pxf://customers/customers.jsonl?PROFILE=s3:json&SERVER=s3') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'); -
Выполните запрос к созданной внешней таблице:
SELECT * FROM customers_r_singleline_3;Вывод должен выглядеть следующим образом:
customer.id | customer.name | ordered_items[1] -------------+---------------+------------------ 1 | John Doe | monitor 2 | Jane Smith | mouse 3 | Bob Brown | 4 | Alice Green | microphone (4 rows)
Чтение JSON-файла с многострочными полями
-
В бакете customers на хосте S3 создайте файл с именем customers.json и следующим содержимым:
{ "customers": [ { "id": 101, "name": "Alice Smith", "ordered_items": [ "laptop", "monitor" ] }, { "id": 102, "name": "Bob Johnson", "ordered_items": [ "keyboard", "mouse", "pad" ] }, { "id": 103, "name": "Charlie Brown", "ordered_items": [ "headphones" ] } ] } -
На мастер-хосте Greengage DB создайте внешнюю таблицу, ссылающуюся на файл customers.json. Сопоставьте текстовый массив
ordered_itemsс текстовым массивом Greengage DB (TEXT[]). В выраженииLOCATIONукажите PXF-профильs3:json, конфигурацию сервера иidв качестве значенияIDENTIFIER. В выраженииFORMATукажитеpxfwritable_import— встроенную кастомную функцию форматирования для операций чтения:CREATE EXTERNAL TABLE customers_r_multiline ( id INT, name TEXT, ordered_items TEXT[] ) LOCATION ('pxf://customers/customers.json?PROFILE=s3:json&SERVER=s3&IDENTIFIER=id') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'); -
Выполните запрос к созданной внешней таблице:
SELECT * FROM customers_r_multiline;Вывод должен выглядеть следующим образом:
id | name | ordered_items -----+---------------+---------------------- 101 | Alice Smith | {laptop,monitor} 102 | Bob Johnson | {keyboard,mouse,pad} 103 | Charlie Brown | {headphones} (3 rows)
Запись JSON-файла с однострочными полями
-
На мастер-хосте Greengage DB создайте пишущую внешнюю таблицу, сохраняющую данные в бакет customers на хосте S3. В выражении
LOCATIONукажите PXF-профильs3:jsonи конфигурацию сервера. В выраженииFORMATукажитеpxfwritable_export— встроенную кастомную функцию форматирования для операций записи:CREATE WRITABLE EXTERNAL TABLE customers_w_singleline ( id INT, name TEXT, ordered_items TEXT[] ) LOCATION ('pxf://customers?PROFILE=s3:json&SERVER=s3') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_export'); -
Вставьте тестовые данные в таблицу
customers_w_singleline:INSERT INTO customers_w_singleline VALUES (1, 'John Doe', ARRAY['laptop', 'monitor']), (2, 'Jane Smith', ARRAY['keyboard', 'mouse', 'pad']), (3, 'Bob Brown', ARRAY['headphones']), (4, 'Alice Green', ARRAY['webcam', 'microphone']); -
Просмотрите содержимое файлов, созданных в бакете customers на хосте S3. Вывод должен выглядеть подобным образом:
{"id":3,"name":"Bob Brown","ordered_items":["headphones"]} {"id":4,"name":"Alice Green","ordered_items":["webcam","microphone"]} {"id":1,"name":"John Doe","ordered_items":["laptop","monitor"]} {"id":2,"name":"Jane Smith","ordered_items":["keyboard","mouse","pad"]}
Запись JSON-файла с многострочными полями
-
На мастер-хосте Greengage DB создайте пишущую внешнюю таблицу, сохраняющую данные в бакет customers на хосте S3. В выражении
LOCATIONукажите PXF-профильs3:json, конфигурацию сервера иcustomersв качестве значенияROOT. В выраженииFORMATукажитеpxfwritable_export— встроенную кастомную функцию форматирования для операций записи:CREATE WRITABLE EXTERNAL TABLE customers_w_multiline ( id INT, name TEXT, ordered_items TEXT[] ) LOCATION ('pxf://customers?PROFILE=s3:json&SERVER=s3&ROOT=customers') FORMAT 'CUSTOM' (FORMATTER='pxfwritable_export'); -
Вставьте тестовые данные в таблицу
customers_w_multiline:INSERT INTO customers_w_multiline VALUES (1, 'John Doe', ARRAY['laptop', 'monitor']), (2, 'Jane Smith', ARRAY['keyboard', 'mouse', 'pad']), (3, 'Bob Brown', ARRAY['headphones']), (4, 'Alice Green', ARRAY['webcam', 'microphone']); -
Просмотрите содержимое файлов, созданных в бакете customers на хосте S3. Вывод должен выглядеть подобным образом:
{"customers":[ {"id":3,"name":"Bob Brown","ordered_items":["headphones"]} ]} {"customers":[ {"id":1,"name":"John Doe","ordered_items":["laptop","monitor"]} ]} {"customers":[ {"id":2,"name":"Jane Smith","ordered_items":["keyboard","mouse","pad"]} ,{"id":4,"name":"Alice Green","ordered_items":["webcam","microphone"]} ]}