8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FirestoreのデータをAPIを叩いて取得・登録するシェルを作ってみる

Last updated at Posted at 2019-05-14

#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を確認していきます。

image.png

上手く登録することができました!

シェルを作ってみる

取得と登録の方法がわかったのでシェルを作っていきます。
処理としては、コピー元/先のプロジェクトIDとコレクションIDを引数で渡し、取得APIでデータ取得、取得したデータをループさせてAPI登録するような簡単なシェルを作ってみます。

シェルの作成には、Jsonの処理にjqを利用しました。
また、日本語にも対応させたいため、【Docker】ubuntuの環境で日本語入力を可能にするを参考に日本語設定をしました。

以下、作ったシェルです。

firestoreCopy.sh
#!/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

シェルを動かしてみる

それでは実際に動かしていきます。
以下の順にパラメータを設定して実行します!

  1. コピー元プロジェクト
  2. コピー元コレクション
  3. コピー先プロジェクト
  4. コピー先コレクション
# 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になります。

image.png

参照元と同じ数、同じドキュメントIDのデータが作成されていることが確認できました!

image.png
分かり辛いですが、改行(ho ge1部分)もコピーされていることができました!

まとめ

簡易的なFirestoreのデータコピーシェルを作成してみました。
ちょっとしたデータのコピーや、既にあるコレクションを複製してバックアップを作りたい。
などの時に利用できればと思います。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?