#Firestoreのデータを別のプロジェクトにコピーしたい!!
Firestoreのデータ別プロジェクトにコピーしたいと思ったのですが、Firestoreのエクスポート/インポート機能はBlaseプランでないと利用できないそうなので、API叩いてデータ取得/登録するちょっとしたシェルを作ってみました。
環境
Docker
ubuntu18.04
やってみる
データ取得をしてみる
Cloud Firestore RESTAPIの使用を参考にデータを取得してみます。
サンプルによると、YOUR_PROJECT_ID部を参照先のプロジェクトIDに変更し、参照したいドキュメントパスをつなげればよいみたいです。
https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/cities/LA
test1-b1a03プロジェクトのtestコレクションを取得するようにして実行してみます。
$ curl 'https://firestore.googleapis.com/v1/projects/test1-b1a03/databases/(default)/documents/test/'
{
"documents": [
{
"name": "projects/test1-b1a03/databases/(default)/documents/test/1",
"fields": {
"string": {
"stringValue": "hoge"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
},
"id": {
"integerValue": "1"
}
},
"createTime": "2019-05-10T10:00:31.788827Z",
"updateTime": "2019-05-10T10:00:31.788827Z"
},
{
"name": "projects/test1-b1a03/databases/(default)/documents/test/22",
"fields": {
"string": {
"stringValue": "hoge"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
},
"id": {
"integerValue": "1"
}
},
"createTime": "2019-05-10T10:01:20.999100Z",
"updateTime": "2019-05-10T10:01:20.999100Z"
},
~~省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]
}
データを取得することができました。
パラメータでpageSizeを指定すると、取得件数を設定することでできるようです。
pageSizeを1件で実施してみます。
$ curl 'https://firestore.googleapis.com/v1/projects/test1-b1a03/databases/(default)/documents/test/?pageSize=1'
{
"documents": [
{
"name": "projects/test1-b1a03/databases/(default)/documents/test/1",
"fields": {
"string": {
"stringValue": "hoge"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
},
"id": {
"integerValue": "1"
}
},
"createTime": "2019-05-10T10:00:31.788827Z",
"updateTime": "2019-05-10T10:00:31.788827Z"
}
],
"nextPageToken": "AJebfAewl38xJK0s9D09W4VACvDSfTZqLCTNJqeNF-74DOW5VQgnHLyu2YVk8CzNvSZjMGcB6u-KblZVFcaB9Fz34VZ-la5pcKIWwg"
}
1件のみ取得することができました。
取得対象のコレクションは2件以上存在するため、取得結果にnextPageTokenが付与されています。
同一URLにpageTokenパラメータを付与し実行することで、次のドキュメントを取得することができるみたいです。
$ curl 'https://firestore.googleapis.com/v1/projects/test1-b1a03/databases/(default)/documents/test/?pageSize=1&pageToken=AJebfAewl38xJK0s9D09W4VACvDSfTZqLCTNJqeNF-74DOW5VQgn
HLyu2YVk8CzNvSZjMGcB6u-KblZVFcaB9Fz34VZ-la5pcKIWwg'
{
"documents": [
{
"name": "projects/test1-b1a03/databases/(default)/documents/test/22",
"fields": {
"string": {
"stringValue": "hoge"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
},
"id": {
"integerValue": "1"
}
},
"createTime": "2019-05-10T10:01:20.999100Z",
"updateTime": "2019-05-10T10:01:20.999100Z"
}
],
"nextPageToken": "AJebfAcF29IQ4MJvLEkTNGxoXvIxKG0Tvpt0GE3Vz-RxeOQgjOIz4IqKsLu4aqXZLVF7sGnmXjXS8nvthFfqNvsTeiESh4vfpLBGQlc"
}
登録してみる
Cloud Firestore APIを参考に実施してきます。
登録を行いたいのでcreateDocumentを使用します。
今回は"test1-b1a03"プロジェクトの"test2"コレクションを対象に、documentIdが"test"のデータを登録するようにしてみます。
また、登録データについては先ほどFireStoreから取得したデータを利用し実行してきます。
リクエストURLの作成
test1-b1a03プロジェクトのtest2コレクションを対象とするようにパスを作成しました。
また、documentIdパラメータを付与し、登録データのドキュメントIDがtestとなるようにしました。
'https://firestore.googleapis.com/v1beta1/projects/test1-b1a03/databases/(default)/documents/test2?documentId=test'
登録データの作成
先ほど取得したデータのnameフィールドと改行削除し、登録用のデータを作成しました。
{
"name": "projects/test1-b1a03/databases/(default)/documents/test/22",
"fields": {
"string": {
"stringValue": "hoge"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
},
"id": {
"integerValue": "1"
}
},
"createTime": "2019-05-10T10:01:20.999100Z",
"updateTime": "2019-05-10T10:01:20.999100Z"
}
{"fields":{"string":{"stringValue":"hoge"},"array":{"arrayValue":{"values":[{"stringValue":"hoge1"},{"stringValue":"hoge2"}]}},"id":{"integerValue":"1"}},"createTime":"2019-05-10T10:01:20.999100Z","updateTime":"2019-05-10T10:01:20.999100Z"}
実行
先ほど作成したリクエストURLと登録データをつなげPOST送信してみます。
$ curl -s 'https://firestore.googleapis.com/v1beta1/projects/test1-b1a03/databases/(default)/documents/test2?documentId=test' -X POST -H 'Content-Type: application/json' -d '
{"fields":{"string":{"stringValue":"hoge"},"array":{"arrayValue":{"values":[{"stringValue":"hoge1"},{"stringValue":"hoge2"}]}},"id":{"integerValue":"1"}},"createTime":"2019-05-10T10:01:20.99910
0Z","updateTime":"2019-05-10T10:01:20.999100Z"}'
{
"name": "projects/test1-b1a03/databases/(default)/documents/test2/test",
"fields": {
"string": {
"stringValue": "hoge"
},
"id": {
"integerValue": "1"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
}
},
"createTime": "2019-05-13T01:17:46.832439Z",
"updateTime": "2019-05-13T01:17:46.832439Z"
}
上手くできているようなので、FireConsoleより、FireStoreを確認していきます。
上手く登録することができました!
シェルを作ってみる
取得と登録の方法がわかったのでシェルを作っていきます。
処理としては、コピー元/先のプロジェクトIDとコレクションIDを引数で渡し、取得APIでデータ取得、取得したデータをループさせてAPI登録するような簡単なシェルを作ってみます。
シェルの作成には、Jsonの処理にjqを利用しました。
また、日本語にも対応させたいため、【Docker】ubuntuの環境で日本語入力を可能にするを参考に日本語設定をしました。
以下、作ったシェルです。
#!/bin/bash
# パラメータ数チェック
if [ $# -ne 4 ]; then
echo "4 parameters are required"
exit 1
fi
# パラメータ取得
exportProjectId=$1
exportCollectId=$2
importProjectId=$3
importCollectId=$4
# 1あたりの取得件数
pageSizeCnt=10
# ページトークン初期値
nPageToken=""
main (){
# ページトークンがなくなるまでループ
while [ "$nPageToken" != "null" ]]; do
# データ取得/登録処理
copyData
done
}
copyData () {
# データ取得用ルクエスト作成
exportRequest="curl -s 'https://firestore.googleapis.com/v1/projects/${exportProjectId}/databases/(default)/documents/${exportCollectId}?pageSize=${pageSizeCnt}&pageToken=${nPageToken}'"
# データ取得
eval $exportRequest > ./tmp.data
# document配下取得
cat ./tmp.data | jq -cr '.documents' > ./tmp.documents
# ページトークン取得
nPageToken=$(cat ./tmp.data | jq -cr '.nextPageToken')
# 要素数取得
len=$(cat ./tmp.documents | jq -cr length)
# 要素分ループ
for i in $( seq 0 $(($len - 1)) ); do
# ドキュメント部取得
cat ./tmp.documents | jq .[$i] > ./tmp.row
# name取得
name=$(cat ./tmp.row | jq -r '.name')
# field取得
cat ./tmp.row | jq -c '.fields' > ./tmp.fields
# createTime、updateTime取得
createTime=$(cat ./tmp.row | jq -c '.createTime')
updateTime=$(cat ./tmp.row | jq -c '.updateTime')
# name部より複製用にID取得
docId=${name##*/}
# 登録リクエスト送信
eval "curl -s 'https://firestore.googleapis.com/v1beta1/projects/${importProjectId}/databases/(default)/documents/${importCollectId}?documentId=${docId}' -X POST -H 'Content-Type: application/json' -d '{"fields": `cat ./tmp.fields`, "createTime": ${createTime}, "updateTime": ${updateTime}}'"
done
}
main
シェルを動かしてみる
それでは実際に動かしていきます。
以下の順にパラメータを設定して実行します!
- コピー元プロジェクト
- コピー元コレクション
- コピー先プロジェクト
- コピー先コレクション
# sh firestoreCopy.sh test1-b1a03 test test2-7efaa copy-test
{
"name": "projects/test2-7efaa/databases/(default)/documents/copy-test/1",
"fields": {
"string": {
"stringValue": "hoge"
},
"id": {
"integerValue": "1"
},
"array": {
"arrayValue": {
"values": [
{
"stringValue": "hoge1"
},
{
"stringValue": "hoge2"
}
]
}
}
},
"createTime": "2019-05-13T03:46:58.336806Z",
"updateTime": "2019-05-13T03:46:58.336806Z"
}
~~省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FireConsoleを参照して、データが登録されていることを確認します。
※左がコピー元、右がコピー先のFirestoreになります。
参照元と同じ数、同じドキュメントIDのデータが作成されていることが確認できました!
分かり辛いですが、改行(ho ge1部分)もコピーされていることができました!
まとめ
簡易的なFirestoreのデータコピーシェルを作成してみました。
ちょっとしたデータのコピーや、既にあるコレクションを複製してバックアップを作りたい。
などの時に利用できればと思います。