はじめに
firestoreにリレーションを持ってデータを新規作成する際のトランザクションの方法がのっていなかったのでその時の解決策を共有します
ドキュメント構成
userがたくさんのeventを持つというようなドキュメント構成となっています
user->event(1対n)
解決法
// 独自でIDを生成する関数
autoId = model => {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let autoId = ''
for (let i = 0; i < 20; i++) {
autoId += chars.charAt(Math.floor(Math.random() * chars.length))
}
return autoId
}
saveNewEvent = async (title, body, uid, navigation) => {
const db = firebase.firestore()
const timestamp = firebase.firestore.Timestamp.now()
const newEventId = autoId('events')
const eventRef = db.collection('events').doc(newEventId)
const userRef = db.collection('users').doc(uid)
// トランザクション開始
db.runTransaction(async transaction => {
await Promise.all(transaction.get(userRef), transaction.get(eventRef))
transaction.set(eventRef, {
userId: uid,
title: title,
body: body,
createdAt: timestamp,
updatedAt: timestamp
})
transaction.update(userRef, {
events: firebase.firestore.FieldValue.arrayUnion(newEventId),
updatedAt: timestamp
})
}) // トランザクション完了
.then(() => {
// 完了後の処理
})
.catch(error => {
console.log(error)
})
}
解説
firestoreでトランザクションを行うときは先に作成コレクション作成前にidを指定する必要があるそうなので今回はautoId()というメソッドを作って独自でIDを生成してそのIDをもとにしてコレクションを作成しています。
まとめ
トランザクション管理は一貫性を持ったデータを保持するためには絶対に必要なので丁寧にやりたいところですね!
参考文献
-
トランザクションとバッチ書き込み(firestore公式ドキュメント)
https://firebase.google.com/docs/firestore/manage-data/transactions?hl=ja#transactions -
【Firestore】ドキュメントの自動生成 ID って被らないの?
https://qiita.com/yukin01/items/dcac3366adcf0fe827a3 -
【Firebase】Firestoreで複数collectionの更新にトランザクションを使う
https://notsleeeping.com/archives/3984