web-dev-qa-db-ja.com

JSONファイルをPostgreSQLにインポートするにはどうすればよいですか?

たとえば、オブジェクトの配列であるcustomers.json(厳密に形成された)ファイルがあり、次のような非常に単純(ネストされたオブジェクトなし)です(重要なこと:既にidが含まれています)。

[
  {
    "id": 23635,
    "name": "Jerry Green",
    "comment": "Imported from facebook."
  },
  {
    "id": 23636,
    "name": "John Wayne",
    "comment": "Imported from facebook."
  }
]

そして、それらをすべてpostgres dbのテーブルcustomersにインポートします。

Json型の列としてimported_jsondataなどのテーブルにリストされたオブジェクトにインポートし、sqlを使用してこれらの値を取得して挿入する必要がある場合、かなり難しい方法を見つけました。実際のテーブルに。

しかし、SQLに触れずにjsonをpostgresにインポートする簡単な方法はありますか?

18
Jerry Green

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);

次に、そのテーブルの単一行にファイルをアップロードします。 psql(またはSQLクライアントが提供するもの)で\copyコマンドを使用します。

\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;
28

コマンドラインpsqlツールを使用して、JSONをSQLステートメントに明示的に埋め込む必要なく、複数行のJSONオブジェクトをpostgresデータベースのJSON列にインポートする簡単な方法があることがわかりました。テクニックは postgresql docs に文書化されていますが、少し隠されています。

秘Theは、バックティックを使用してJSONをpsql変数にロードすることです。たとえば、次のような/ tmp/test.jsonの複数行の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)

カバーの下では、これはSQLにJSONを埋め込むだけですが、psqlが補間自体を実行できるようにする方がはるかに便利です。

25
Doctor Eval

ファイルからjsonをインポートする最も簡単な方法は、ファイルから単一のjsonをインポートするのではなく、単一の列csvをインポートするようです:1行のjsonのリスト:

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(行)ごとに1レコードがtテーブルに追加されます。

"\ copy from"インポートはcsv用に作成されたため、データを1行ずつロードします。結果として、後で分割される単一のjson配列ではなく、行ごとに1つのjsonを読み取り、中間テーブルを使用しません。

さらに、入力jsonファイルが大きすぎる場合に発生する最大入力行サイズの制限に達することはありません。

したがって、まず入力を単一の列csvに変換してから、copyコマンドを使用してインポートします。

2
user1767316