前回の記事「kintone(キントーン)コマンドラインツールの活用方法」では、kintone(キントーン)コマンドラインツール「cli-kintone」の基本的な使い方を見てきました。標準機能でのインポートに難儀する「サブテーブル」や「添付ファイル」まで対応できるという本ツールならではのメリットを確認したところです。
今回は一歩使い方を押し進めて、データ移行をやってみたいと思います! 今回はMacintoshで実行していますが、基本的な操作方法は前回と同様です。
手順と注意点
手順
(STEP1)コピー元のアプリからCSVファイルと添付ファイルを一挙にダウンロード
(STEP2)ビルトインフィールド(レコードIDや作成日時等)の列を削除
(STEP3)コピー先のアプリにCSVファイルと添付ファイルを一挙にアップロード(全て新規登録)
注意点
(1)今回は、コピー元アプリの全データをダウンロードして、コピー先アプリへ新規登録レコードとしてアップロードする
(2)データ移行なので、環境はクロスドメインもOKですが、アプリの構造は同じである(テンプレートで移す等して準備しましょう)
(3)運用途中で必須化したフィールドは、当該フィールドの値が空のレコードの存在が原因でエラーになる可能性があるため、チェックしておく
(4)ルックアップフィールドを含むアプリであれば、ルックアップ元のキーフィールドが重複禁止でないと反映できない(参考)
(5)組織/グループ/ユーザー選択フィールドを有する場合には、コピー元とコピー先で設定が揃っていない値はエラーになるため、事前にこれらの設定も移す等対応しておく
データ移行を実践する
早速やっていきたいと思います。
サブドメイン「subdomain_A」のアプリ「app.A(app_id_A)」のレコードを、サブテーブル及び添付ファイル込みでサブドメイン「subdomain_B」のアプリ「app.B(app_id_B)」に移行します。両アプリは勿論同じ(構造の)アプリです。
(STEP1)コピー元アプリからのCSVファイル及び添付ファイルのダウンロード
作業用ディレクトリを「./work」として、次のようなコマンドを実行します。各コマンドオプション、頭に入っていなければ前回の記事等を見直しましょう。
./cli-kintone -a app_id_A -d subdomain_A -t token_A -q "order by \$id asc" -c "" -b ./work > ./work/backup.csvポイントは、レコードID($id)の昇順で取得して後々アップロード時に文字通り昇順で順次登録できるようここで準備している点でしょうか。細かいところとしては、レコードIDを指す「$id」を指定するところで、「$」に対するエスケープが必要なところも押さえておきたいところです。
(STEP2)ビルトインフィールドの列を削除
レコードIDや作成日時等のビルトインフィールドは新規登録用のCSVに入れたままだとエラーになりますので、ビルトインフィールドの列を削除しておきます。
ビルトインフィールドは、次の項目です。フィールドコードを変更している場合は読み替えてください。$id レコード番号 $revision 作成者 作成日時 更新者 更新日時 ステータスまた、ビルトインフィールドの列削除後のCSVファイルをここでは、「./work」配下に「upload.csv」として保存しておきましょう。
(STEP3)コピー先アプリへのCSVファイル及び添付ファイルのアップロード
作業用ディレクトリ「./work」配下にはアップロード用のCSVファイル「upload.csv」とダウンロードしてきた添付ファイルがある状況です。ここで打つべき、コピー先アプリにデータを登録するコマンドは次のとおりです。
./cli-kintone -a app_id_B -d subdomain_B -t token_B -b ./work/ -f ./work/upload.csvエラー等特になければ、何とこれだけでサブテーブルや添付ファイルも込みでアップロードされます! 添付ファイルのフォルダ名は元のアプリのレコードID等が利用されているのですが、特に書き換え等は不要です。これはありがたい!
一連の流れの自動化
3ステップでデータ移行できてしまいますが、もっと楽にしたいものです。この3ステップを一連で流すスクリプトを書いてみました。ビルトインフィールドの削除がメインの処理になる今回のスクリプトはPython2.7で書いてみました。
Python 2.7 スクリプティング
# -*- coding: utf-8 -*- # # migration.py # # Usage: python migration.py src_subdomain src_space_id src_app_id src_api_token tar_subdomain tar_space_id tar_app_id tar_api_token # ※ Setting space_id 0, normal space processing # import csv, sys, subprocess params = sys.argv # コマンドライン引数 argc = len(params) if (argc != 9): print('Usage: python migration.py src_subdomain src_space_id src_app_id src_api_token tar_subdomain tar_space_id tar_app_id tar_api_token') quit() BUILTIN_LIST = ['$id', 'レコード番号', '$revision', '作成者', '作成日時', '更新者', '更新日時', 'ステータス'] # ビルトインフィールド CLI_KINTONE = './cli-kintone' # コマンドラインツール WORK_DIR = './work1' # 作業用ディレクトリ DL_CSV = 'backup.csv' # ダウンロードCSVのファイル名 UL_CSV = 'upload.csv' # アップロード用CSVのファイル名 # コピー元アプリ情報 src_subdomain = params[1] # サブドメイン src_space_id = params[2] # ゲストスペースのID(0の時には通常のスペース) src_app_id = params[3] # アプリID src_api_token = params[4] # APIトークン # コピー先アプリ情報 tar_subdomain = params[5] # サブドメイン tar_space_id = params[6] # ゲストスペースのID(0の時には通常のスペース) tar_app_id = params[7] # アプリID tar_api_token = params[8] # APIトークン ## 作業用ディレクトリ作成 mkdir_cmd = 'mkdir {}'.format(WORK_DIR) # コマンド生成 subprocess.call(mkdir_cmd, shell=True) # コマンド実行 ## バックアップコマンド(ファイルとCSVをダウンロード) dl_cmd = '{} -a {} -d {} -t {} -q {} -b {} > {}/{}'.format(CLI_KINTONE, src_app_id, src_subdomain, src_api_token, '"order by \$id asc"', WORK_DIR, WORK_DIR, DL_CSV) print(dl_cmd) if src_space_id is not '0': dl_cmd = dl_cmd + ' -g {}'.format(src_space_id) # コマンド生成 subprocess.call(dl_cmd, shell=True) # コマンド実行 ## ファイル処理(ビルトインフィールドを削除してアップロード用ファイルを作成) with open(WORK_DIR + '/' + DL_CSV, 'r') as fin: # ファイルを読込モードでオープン reader = csv.reader(fin) # readerオブジェクトを作成 reader_t = list(map(list, list(zip(*reader)))) # ビルトインフィールド削除前に、読込CSVの転置 i=0 for x in reader_t: # ビルトインフィールドの行を削除 if reader_t[i][0] in BUILTIN_LIST: reader_t.pop(i) continue i += 1 body = list(map(list, list(zip(*reader_t)))) # ビルトインフィールド削除後に、書込CSV用に転置 with open(WORK_DIR + '/' + UL_CSV, 'w') as fout: # ファイルを書込モードでオープン writer = csv.writer(fout) # writerオブジェクトを作成 writer.writerows(body) # アップロード用CSVを書き込む ## アップロードコマンド(ファイルとCSVをアップロード) ul_cmd = '{} -a {} -d {} -t {} -b {} -f {}/{}'.format(CLI_KINTONE, tar_app_id, tar_subdomain, tar_api_token, WORK_DIR, WORK_DIR, UL_CSV) print(ul_cmd) if tar_space_id is not '0': ul_cmd = ul_cmd + ' -g {}'.format(tar_space_id) # コマンド生成 subprocess.call(ul_cmd, shell=True) # コマンド実行実行例
今回のケースに、このスクリプトを使うと次のようになります。
python migration.py subdomain_A 0 app_id_A token_A subdomain_B 0 app_id_B token_BゲストスペースのIDを指定する部分は、0を指定すると通常のアプリへの対応となります。
まとめ
やってみると、意外とあっけないものです! 先に挙げた注意点に沿ってデータがメンテナンスされていれば、殆どつまづくことなく実行できると思いますので、是非お試しください。
関連記事