FirestoreでAuto Increment Fieldを作成
Firestoreで連番となるフィールドの作成方法を紹介します。
肝はFirestoreのtransactionを使って原子性(Atomicity)、一貫性(Consistency)、独立性(Isolation)を保証することです。
汎用的に使えるgenerateSequenceNumber関数を作成してみました。
- manage_collection: 連番を生成するターゲットcollectionを管理するcollection名
- target_collection: 連番を生成するターゲットとなるcollection名
- numberField: 連番を生成したいフィールド名
を渡して使います。
function generateSequenceNumber(db, manage_collection, target_collection, numberField) {
const docRef = db.collection(manage_collection).doc(target_collection);
return db.runTransaction((transaction) => {
return transaction.get(docRef).then((doc) => {
if (!doc.exists) {
transaction.set(docRef, { [numberField]: 1});
return 1;
}
const newNumber = typeof doc.data()[numberField] === 'undefined' ? 1 : doc.data()[numberField] + 1;
await transaction.update(docRef, { [numberField]: newNumber });
return newNumber;
});
})
}
});
target_collectionのdocument追加時に連番(numberフィールド)を振る場合の使用例を下記に示します。
const db = admin.firestore();
// generateSequenceNumberの引数のcollection名やフィールド名は、管理しやすい名前を付けられれば、なんでもOKです。
generateSequenceNumber(db, 'manage_collection', 'target_collection', 'number')
.then((number) => {
db.collection('target_collection').add({
number: number,
some_filed: 'some value', // 連番以外の他のフィールド
});
補足
公式のドキュメントによると、Firestoreのtransactionの特徴としては下記があります。
- getの後に、set、update、deleteの操作が必要。
- transactionが更新されたdocumentをgetした場合は、transactionは失敗となり、再度そのtransactionが実行される。
コメント