こんにちは。バックエンドエンジニアの木暮です。
今回はfirestoreのREST APIを使う機会がありましたので
TypeScriptでの使用方法を紹介させていただきます!
私の読解力の低さのせいだとは思いますが、なかなか公式ドキュメントを読んでもすんなりと動かすことができませんでした。
なので備忘録も兼ねてこちらを書かせていただきました!初めて使う方の手助けになれば幸いです!
下準備
まず、REST APIを使用するにあたってjwtトークンを取得する必要があります。
jwtトークンは以下のメソッドを使用して取得します。 https://firebase.google.com/docs/reference/js/v8/firebase.User#getidtoken
以下にログインユーザのjwtトークンを取得する例を示します。
const getJwt = async (): Promise<string> => { // firebaseを使用するための下準備 const app = initializeApp({ apiKey: "dummyApiKey", projectId: "dummyProjectId", }); // firebaseログイン情報 const email = "dummy@example.com"; const password = "dummyPassword"; // firebaseにログイン await signInWithEmailAndPassword(getAuth(app), email, password); // Authオブジェクトを取得 const auth = getAuth(app); // JWTトークンを取得 const jwt = await auth.currentUser?.getIdToken(); if (!jwt) { throw new Error("Failed to get JWT token."); } return jwt; };
上記のメソッドで取得したトークン文字列はBearer認証で使用します。
ドキュメントの作成
fetchを使用してのドキュメントの作成を実行します。
Method: projects.databases.documents.createDocument | Firebase
段階を踏んで解説していきます。 まずは最初に定義する変数について解説です。
const jwt = await getJwt(); const collectionName = "hogeCollection"; const projectId = "dummyProjectId"; const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}`;
collectionName
にはドキュメントの書き込み先となるコレクションの名前を指定してください。
projectId
には自身のプロジェクトのIDを指定します。
requestUrl
ではcollectionName
とprojectId
を使ってリクエスト先URLを組み立てています。
次にリクエストボディ部分の解説です。
REST Resource: projects.databases.documents | Firebase
上記ドキュメント内のfieldsに沿ってボディを設定します。
"fields": { string: { object (Value) }, ... },
この形でリクエストのボディを設定して設定値をJSON.stringify
を使用JSON文字列として設定します。
object (Value)
に設定できる値は以下のドキュメントに書かれています。
Value | Firestore | Google Cloud
よく使う設定値をピックアップして解説します。
定義 | 設定する値 | 例 |
---|---|---|
nullValue | nullを設定 | null |
booleanValue | bool値を設定 | true |
integerValue | 整数値を設定 | "123" |
doubleValue | 倍精度浮動小数点数型を設定 | 123.456 |
timestampValue | ISO 8601フォーマットでtimestampを設定 | "2014-10-02T15:01:23Z" |
stringValue | 文字列を設定 | "Hello World" |
arrayValue | 配列を設定 | サンプルコード参照 |
mapValue | mapを設定 | サンプルコード参照 |
そのほかの設定できる値や詳細は上記のリンクを参照してください。
実際にobject (Value)
を設定する際は以下のような形式で設定を行います。
{ドキュメントの項目名}: {値の型}:{値}, }
具体的なリクエストボディは以下のようになります。
const requestBody = JSON.stringify({ fields: { null: { nullValue: null, }, bool: { booleanValue: true, }, int: { integerValue: "123", }, double: { doubleValue: 123.456, }, timestamp: { timestampValue: new Date().toISOString(), }, string: { stringValue: "Hello World", }, array: { arrayValue: { values: [ { stringValue: "Hello", }, { stringValue: "World", }, ], }, }, map: { mapValue: { fields: { hello: { stringValue: "Hello", }, world: { stringValue: "World", }, }, }, }, }, });
最後にリクエストヘッダーの設定についてです。
const fetchOptions = { method: "POST", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, body: requestBody, };
headers
のAuthorization
に冒頭で取得しているトークン文字列を設定します。
HTTPリクエストメソッドはPOST
になります。
全体では以下のような実装になります。
const store = async () => { const jwt = await getJwt(); const collectionName = "hogeCollection"; const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}`; const requestBody = JSON.stringify({ fields: { null: { nullValue: null, }, bool: { booleanValue: true, }, int: { integerValue: "123", }, double: { doubleValue: 123.456, }, timestamp: { timestampValue: new Date().toISOString(), }, string: { stringValue: "Hello World", }, array: { arrayValue: { values: [ { stringValue: "Hello", }, { stringValue: "World", }, ], }, }, map: { mapValue: { fields: { hello: { stringValue: "Hello", }, world: { stringValue: "World", }, }, }, }, }, }); const fetchOptions = { method: "POST", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, body: requestBody, }; await fetch(requestUrl, fetchOptions); };
上記メソッドを実行後にfirestoreコンソールからすると登録できていることが確認できました
登録時のドキュメント名を指定したい場合はリクエストURLに?documentId={ドキュメント名}
の形でクエリパラメータを追加します。
以下のURLでリクエストを送ると指定したドキュメント名で登録されていることが確認できます。
const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}?documentId=hoge`
ドキュメントの更新
Method: projects.databases.documents.patch | Firebase
ドキュメントの更新はrequestURLを以下のように指定します
const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${documentPath}`;
HTTPリクエストメソッドにはPATCHを指定します。
const fetchOptions = { method: "PATCH", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, body: requestBody, };
全体的な実装は以下のようになります。
以下の例はhogeCollectionのhogeドキュメントをnullで更新しています。
const update = async () => { const jwt = await getJwt(); const collectionName = "hogeCollection"; const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}/hoge`; const requestBody = JSON.stringify({ fields: { null: { nullValue: null, }, }, }); const fetchOptions = { method: "PATCH", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, body: requestBody, }; await fetch(requestUrl, fetchOptions); };
上記メソッドを実行後の状態は以下のようになります
ドキュメントの取得
ドキュメントの単一取得を説明します。
Method: projects.databases.documents.get | Firebase
サンプルコードはこのようになります
const get = async () => { const jwt = await getJwt(); const collectionName = "hogeCollection"; const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}/hoge`; const fetchOptions = { method: "GET", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, }; const res = await fetch(requestUrl, fetchOptions); const data = await res.json(); console.log(data); };
リクエスト先は更新時と同様の指定方法になります。 そして、HTTPリクエストメソッドはGETになります。 実行してレスポンスの確認すると以下のようになっています。
{ name: 'projects/dummy-project-id/databases/(default)/documents/hogeCollection/hoge', fields: { null: { nullValue: null } }, createTime: '2024-09-22T04:28:13.256088Z', updateTime: '2024-09-22T04:36:37.323123Z' }
nameキーには取得先が設定されています。
fieldsキーには取得したドキュメントの値が設定されています。今回はnullで更新後のドキュメントを取得しているので簡単な値しか取れていません。
そして、createTimeにはドキュメントの作成日時、updateTimeにはドキュメントの更新日時が設定されます。
ドキュメントの削除
最後にドキュメントの削除を紹介します。
Method: projects.databases.documents.delete | Firebase
deleteもリクエスト先は更新、取得同様になります。 違いはHTTPリクエストメソッドがDELETEになる点のみです。
const _delete = async () => { const jwt = await getJwt(); const collectionName = "hogeCollection"; const requestUrl = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/${collectionName}/hoge`; const fetchOptions = { method: "DELETE", headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json", }, }; await fetch(requestUrl, fetchOptions); };
実行後、firestoreコンソールから該当のドキュメントが削除されたことが確認できます。
最後に
ほんの一部にはなりますが、firestoreのREST APIを通してのドキュメントの作成、更新、取得、削除の紹介をさせていただきました。 他にもAPIがありますので、またどこかで機会がありましたら紹介させていただきたいと思います!
最後まで読んでくださりありがとうございました!
この記事を読んで興味を持って下さった方がいらっしゃればカジュアルにお話させていただきたく、是非ご応募をお願いいたします!!Wantedly / Green