Как импортировать JSON файл в PostgreSQL?
Например, у меня есть файл customers.json
, который представляет собой массив объектов (строго сформированный) и довольно простой (без вложенных объектов) вроде этого (что важно: оно уже включает идентификаторы):
[
{
"id": 23635,
"name": "Jerry Green",
"comment": "Imported from facebook."
},
{
"id": 23636,
"name": "John Wayne",
"comment": "Imported from facebook."
}
]
И я хочу импортировать их все в свой postgres db в таблицу customers
.
Я нашел некоторые довольно сложные способы, когда я должен был импортировать его как столбец json-типа в таблицу типа imported_json
и столбец с именем data
с указанными там объектами, затем использовать sql для получения этих значений и вставить его в реальная таблица.
Но есть ли простой способ импортировать json в postgres, не касаясь sql?
Ответы
Ответ 1
Вы можете передать JSON в оператор SQL, который извлекает информацию и вставляет ее в таблицу. Если атрибуты JSON имеют точно имя в качестве столбцов таблицы, вы можете сделать что-то вроде этого:
with customer_json (doc) as (
values
('[
{
"id": 23635,
"name": "Jerry Green",
"comment": "Imported from facebook."
},
{
"id": 23636,
"name": "John Wayne",
"comment": "Imported from facebook."
}
]'::json)
)
insert into customer (id, name, comment)
select p.*
from customer_json l
cross join lateral json_populate_recordset(null::customer, doc) as p
on conflict (id) do update
set name = excluded.name,
comment = excluded.comment;
Новые клиенты будут вставлены, существующие будут обновлены. "Волшебная" часть - это json_populate_recordset(null::customer, doc)
, которая генерирует реляционное представление объектов JSON.
Вышеприведенное определение таблицы выглядит следующим образом:
create table customer
(
id integer primary key,
name text not null,
comment text
);
Если данные предоставлены в виде файла, вам нужно сначала поместить этот файл в какую-нибудь таблицу в базе данных. Что-то вроде этого:
create unlogged table customer_import (doc json);
Затем загрузите файл в одну строку этой таблицы, например. используя команду \copy
в psql
(или что-то, что предлагает ваш клиент SQL):
\copy customer_import from 'customers.json' ....
Затем вы можете использовать вышеуказанный оператор, просто удалите CTE и используйте промежуточную таблицу:
insert into customer (id, name, comment)
select p.*
from customer_import l
cross join lateral json_populate_recordset(null::customer, doc) as p
on conflict (id) do update
set name = excluded.name,
comment = excluded.comment;
Ответ 2
Оказывается, существует простой способ импортировать многострочный объект JSON в столбец JSON в базе данных postgres с помощью инструмента командной строки psql без необходимости явного встраивания JSON в оператор SQL. Техника описана в документации postgresql, но она немного скрыта.
Хитрость заключается в том, чтобы загрузить JSON в переменную psql с помощью обратных галочек. Например, учитывая многострочный файл JSON в /tmp/test.json, например:
{
"dog": "cat",
"frog": "frat"
}
Мы можем использовать следующий SQL для загрузки его во временную таблицу:
sql> \set content 'cat /tmp/test.json'
sql> create temp table t ( j jsonb );
sql> insert into t values (:'content');
sql> select * from t;
который дает результат:
j
────────────────────────────────
{"dog": "cat", "frog": "frat"}
(1 row)
Вы также можете выполнять операции с данными напрямую:
sql> select :'content'::jsonb -> 'dog';
?column?
──────────
"cat"
(1 row)
Под прикрытием это просто встраивание JSON в SQL, но гораздо проще позволить psql выполнить саму интерполяцию.
Ответ 3
Самый простой способ импортировать JSON из файла
не импортировать ни одного JSON из файла
а точнее один столбец csv: список jsons из одной строки:
data.json:
{"id": 23635,"name": "Jerry Green","comment": "Imported from facebook."}
{"id": 23636,"name": "John Wayne","comment": "Imported from facebook."}
тогда под psql:
create table t ( j jsonb )
\copy t from 'd:\path\data.json'
Одна запись для каждого json (строки) будет добавлена в таблицу t.
Импорт "\ copy from" был сделан для csv, и как таковой
загружает данные построчно.
В результате чтение одного JSON на строку
а не один массив JSON для последующего разделения,
не будет использовать какую-либо промежуточную таблицу.
Более того, вы не достигнете ограничения максимального размера входной строки, которое возникнет, если ваш входной json файл слишком большой.
Таким образом, я сначала преобразовал бы ваш ввод в один столбец csv, а затем импортировал его с помощью команды copy.
Ответ 4
Что если JSON выглядит так
[ { "id":"1", "name":"abc_xyz", "language":"English", "title":"facebook", "description":"This is a test", "categories":[ "https://facebook/category/28", "https://facebook/category/29", "https://facebook/category/30", "https://facebook/category/31" ] }, "id":"2", "name":"abc_xyz", "language":"French", "title":"Twitter", "description":"This is another test", "categories":[ "https://twitter/category/2", "https://twitter/category/23", "https://twitter/category/35" ] } ]
Тогда как нам загрузить его в таблицу или две таблицы (1-й Таблица (скажем, TableA) будет содержать столбцы: id, name, language, description
а вторая таблица будет содержать связь id and Category
Например: TableB будет содержать
ID | CatID
1 | 28
1 | 29
1 | 30
1 | 30
и т.д.