🔥

フロントエンド(Nuxt.js)でのFireStoreの文法まとめ

2024/07/21に公開

Firestoreでのフロントエンドでの処理についてまとめました。
Firestoreでの繋ぎこみやインスタンスを初期化は済んでいる前提で記載します。

全データを取得(getDocs)

getDocsメソッドを使用すると、複数のドキュメントの内容を取得できます。

  const fetchData = async () => {
    const querySnapshot = await getDocs(collection(db, 'todos'))
    querySnapshot.forEach((doc) => {
      const todo = {
        id: doc.id,
        uuid: doc.id,
        ...doc.data()
      }
    })
    return fetchedTodos.value
  }

単一データを取得(Doc)

Docメソッドを使用すると、単一のドキュメントの内容を取得できます。

  // 単一データの取得処理
  const getTodo = async (route: string) => {
    try {
      const todoRef = doc(db, 'todos', route)
      const todoSnap = await getDoc(todoRef)
      if (todoSnap.exists()) {
        const todo = todoSnap.data()
        return todo
      }
    } catch (e) {
      alert('エラーが起きました')
    }
  }

queryでの絞り込み(getDocs)

queryを使うと、データの絞り込みが可能です。
Reactでの例ですが下記のようになります。
whereで、指定のコレクションを絞り込むことができます。
この場合だと、email一致で、カテゴリーが東京リベンジャーズの記事を取得しています。

  const myTokyoPosts = query(
    postsRef,
    where('email', '==', user.email),
    where('category', '==', '東京リベンジャーズ'),
  )
  }

  const getTokyoPosts = async () => {
    //firestoreからデータ取得
    await getDocs(myTokyoPosts).then((querySnapshot) => {
      //コレクションのドキュメントを取得
      setTokyo(
        querySnapshot.docs.map((data) => {
          //配列なので、mapで展開する
          return { ...data.data(), id: data.id }
          //スプレッド構文で展開して、新しい配列を作成
        }),
      )
    })
  }

他にもorderBy("name", "desc"), とすれば、並び替えもできたり、
limit(3)を付ければ、データの取得制限数も設定できます。

データの追加(addDoc)

addDocメソッドを使うと、 Firestore側でIDが自動的に生成されて、データが保存されます

  // Todoの登録処理
  const addTodo = async (name, content, period, category, priority, date) => {
    useLoading.openAppLoading();
    try {
      await addDoc(collection(db, "todos"), {
        name: name,
        content: content,
        done: false,
        period: period,
        category: category,
        priority: priority,
        date: date,
      });
      useLoading.closeAppLoading();
      useModal.openAppModal("Todoを投稿しました");
      await navigateTo("/todo");
    } catch (e) {
      console.error("Error adding document: ", e);
    }
  };

データの編集(updateDoc)

データを更新したい場合にはupdateDocメソッドを用います。

  // Todoの編集処理
  const editTodo = async (route, name, content, period, priority) => {
    useLoading.openAppLoading();
    try {
      const docRef = doc(db, "todos", route);
      await updateDoc(docRef, {
        name: name,
        content: content,
        period: period,
        priority: priority,
      });
      useLoading.closeAppLoading();
      useModal.openAppModal("Todoを編集しました");
      await navigateTo("/todos/" + route);
    } catch (e) {
      console.log(e);
    }
  };

データの削除(deleteDoc)

データを削除したい場合にはdeleteDocメソッドを用います。

  const deleteTask = async (route: string) => {
    try {
      const docRef = doc(db, "todos", route);
      await deleteDoc(docRef);
      useModal.openAppModal("Todoを削除しました");
      navigateTo("/todo");
    } catch (e) {
      alert("エラーが起きました");
      console.log(e);
    }
  };

バッチ書き込み (batch)

バッチ書き込みとは、1 つ以上のドキュメントに対して書き込みを行う一連のオペレーションです。
つまり、投稿と更新と削除を組み合わせて、一連の流れで実行できます
下記の例では、バッチ処理を使って、複数投稿(連続して投稿)の例です

// 複数登録処理
  const multiAddTodo = async (todos: Array<multiTodoParams>) => {
    const batch = writeBatch(db)
    try {
      todos.forEach((todo: multiTodoParams) => {
        const todoDocRef = doc(db, 'todos', todo.date + todo.suffix)
        batch.set(todoDocRef, {
          name: todo.name,
          content: todo.content,
          done: false,
          period: todo.period,
          category: todo.category,
          priority: todo.priority,
          date: todo.date
        })
      })
      await batch.commit()
      useModal.openAppModal('Todoを投稿しました', 'success')
      navigateTo('/todos')
    } catch (e) {
      useLoading.closeAppLoading()
      useModal.openAppModal('Todoの投稿に失敗しました', 'error')
    }
  }

トランザクション(runTransaction)

トランザクションは、一連の流れの中で、もし一つでも失敗すれば、エラーが返され、
データベースには何も書き込まれません。
トランザクションをロールバックなどは、Cloud Firestore により自動的に実行されるようです。
下記は今後試していきたいです。

import { runTransaction } from "firebase/firestore";

try {
  await runTransaction(db, async (transaction) => {
    const sfDoc = await transaction.get(sfDocRef);
    if (!sfDoc.exists()) {
      throw "Document does not exist!";
    }

    const newPopulation = sfDoc.data().population + 1;
    transaction.update(sfDocRef, { population: newPopulation });
  });
  console.log("Transaction successfully committed!");
} catch (e) {
  console.log("Transaction failed: ", e);
}

まとめ

バックエンドが苦手なので、FireStoreには大変お世話になっています。
色々なことができるので、ぜひ使ってみてください

参考

https://firebase.google.com/docs/firestore?hl=ja&_gl=11dltssz_upMQ.._gaMTYxNjgwMTI4Ny4xNzIxNDQ4NTYz_ga_CW55HF8NVT*MTcyMTQ0ODU2My4xLjAuMTcyMTQ0ODU2My4wLjAuMA..

Discussion